[Synthesizers] Implement default overrides

Default time, fade, loop count, and sample rate may now be overridden.

Synchronized preferences strings tables. Spanish translation of new
options pending, new releases won't be pushed until they're complete.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
xcode15
Christopher Snowhill 2022-07-01 22:06:08 -07:00
parent 33a24d4d3e
commit 5d7a9798fe
28 changed files with 538 additions and 79 deletions

View File

@ -581,6 +581,11 @@ static AppController *kAppController = nil;
[userDefaultsValuesDict setObject:barColor forKey:@"spectrumBarColor"]; [userDefaultsValuesDict setObject:barColor forKey:@"spectrumBarColor"];
[userDefaultsValuesDict setObject:dotColor forKey:@"spectrumDotColor"]; [userDefaultsValuesDict setObject:dotColor forKey:@"spectrumDotColor"];
[userDefaultsValuesDict setObject:@(150.0) forKey:@"synthDefaultSeconds"];
[userDefaultsValuesDict setObject:@(8.0) forKey:@"synthDefaultFadeSeconds"];
[userDefaultsValuesDict setObject:@(2) forKey:@"synthDefaultLoopCount"];
[userDefaultsValuesDict setObject:@(44100) forKey:@"synthSampleRate"];
// Register and sync defaults // Register and sync defaults
[[NSUserDefaults standardUserDefaults] registerDefaults:userDefaultsValuesDict]; [[NSUserDefaults standardUserDefaults] registerDefaults:userDefaultsValuesDict];
[[NSUserDefaults standardUserDefaults] synchronize]; [[NSUserDefaults standardUserDefaults] synchronize];

View File

@ -7,6 +7,7 @@
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
833A899A286FF2FD0022E036 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 833A8999286FF2FD0022E036 /* Cocoa.framework */; };
833AFD3620E4ED9D00F0C21E /* libAdPlug.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83AA434020E4EC8C00E861B2 /* libAdPlug.framework */; }; 833AFD3620E4ED9D00F0C21E /* libAdPlug.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83AA434020E4EC8C00E861B2 /* libAdPlug.framework */; };
83747C6F2862DDDB0021245F /* Shared.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 83747C6D2862DDDB0021245F /* Shared.xcconfig */; }; 83747C6F2862DDDB0021245F /* Shared.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 83747C6D2862DDDB0021245F /* Shared.xcconfig */; };
83C2806320E4ECAD00823BF9 /* libAdPlug.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83AA434020E4EC8C00E861B2 /* libAdPlug.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 83C2806320E4ECAD00823BF9 /* libAdPlug.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83AA434020E4EC8C00E861B2 /* libAdPlug.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
@ -51,6 +52,7 @@
/* End PBXCopyFilesBuildPhase section */ /* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
833A8999286FF2FD0022E036 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
83747C6D2862DDDB0021245F /* Shared.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Shared.xcconfig; sourceTree = "<group>"; }; 83747C6D2862DDDB0021245F /* Shared.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Shared.xcconfig; sourceTree = "<group>"; };
83D3C5F3201C674D005564CB /* AdPlug.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AdPlug.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; 83D3C5F3201C674D005564CB /* AdPlug.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AdPlug.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
83D3C5F6201C674D005564CB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 83D3C5F6201C674D005564CB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@ -77,6 +79,7 @@
files = ( files = (
83D3C6A6201D3951005564CB /* libbinio.framework in Frameworks */, 83D3C6A6201D3951005564CB /* libbinio.framework in Frameworks */,
833AFD3620E4ED9D00F0C21E /* libAdPlug.framework in Frameworks */, 833AFD3620E4ED9D00F0C21E /* libAdPlug.framework in Frameworks */,
833A899A286FF2FD0022E036 /* Cocoa.framework in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -141,6 +144,7 @@
83D3C602201C675D005564CB /* Frameworks */ = { 83D3C602201C675D005564CB /* Frameworks */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
833A8999286FF2FD0022E036 /* Cocoa.framework */,
83D3C6A7201D3951005564CB /* libbinio.framework */, 83D3C6A7201D3951005564CB /* libbinio.framework */,
83D3C603201C6775005564CB /* libAdPlug.xcodeproj */, 83D3C603201C6775005564CB /* libAdPlug.xcodeproj */,
); );

View File

@ -17,6 +17,8 @@
CPlayer* m_player; CPlayer* m_player;
Copl* m_emu; Copl* m_emu;
double sampleRate;
unsigned int subsong, samples_todo; unsigned int subsong, samples_todo;
id<CogSource> source; id<CogSource> source;

View File

@ -47,7 +47,14 @@ static CAdPlugDatabase *g_database = NULL;
- (BOOL)open:(id<CogSource>)s { - (BOOL)open:(id<CogSource>)s {
[self setSource:s]; [self setSource:s];
m_emu = new CNemuopl(44100); sampleRate = [[[[NSUserDefaultsController sharedUserDefaultsController] defaults] valueForKey:@"synthSampleRate"] doubleValue];
if(sampleRate < 8000.0) {
sampleRate = 44100.0;
} else if(sampleRate > 192000.0) {
sampleRate = 192000.0;
}
m_emu = new CNemuopl(sampleRate);
NSString *path = [[s url] absoluteString]; NSString *path = [[s url] absoluteString];
NSRange fragmentRange = [path rangeOfString:@"#" options:NSBackwardsSearch]; NSRange fragmentRange = [path rangeOfString:@"#" options:NSBackwardsSearch];
@ -68,7 +75,7 @@ static CAdPlugDatabase *g_database = NULL;
samples_todo = 0; samples_todo = 0;
length = m_player->songlength(subsong) * 441 / 10; length = m_player->songlength(subsong) * sampleRate / 1000.0;
current_pos = 0; current_pos = 0;
m_player->rewind(subsong); m_player->rewind(subsong);
@ -81,7 +88,7 @@ static CAdPlugDatabase *g_database = NULL;
- (NSDictionary *)properties { - (NSDictionary *)properties {
return @{ @"bitrate": @(0), return @{ @"bitrate": @(0),
@"sampleRate": @(44100.0), @"sampleRate": @(sampleRate),
@"totalFrames": @(length), @"totalFrames": @(length),
@"bitsPerSample": @(16), // Samples are short @"bitsPerSample": @(16), // Samples are short
@"floatingPoint": @(NO), @"floatingPoint": @(NO),
@ -106,7 +113,7 @@ static CAdPlugDatabase *g_database = NULL;
if(!samples_todo) { if(!samples_todo) {
running = m_player->update() && running; running = m_player->update() && running;
if(!dont_loop || running) { if(!dont_loop || running) {
samples_todo = 44100 / m_player->getrefresh(); samples_todo = (int)ceil(sampleRate / m_player->getrefresh());
current_pos += samples_todo; current_pos += samples_todo;
} }
} }
@ -132,7 +139,7 @@ static CAdPlugDatabase *g_database = NULL;
while(current_pos < frame) { while(current_pos < frame) {
m_player->update(); m_player->update();
current_pos += 44100 / m_player->getrefresh(); current_pos += (long)ceil(sampleRate / m_player->getrefresh());
} }
samples_todo = (UInt32)(frame - current_pos); samples_todo = (UInt32)(frame - current_pos);

View File

@ -17,7 +17,7 @@ extern gme_err_t readCallback(void* data, void* out, int count);
@interface GameDecoder : NSObject <CogDecoder> { @interface GameDecoder : NSObject <CogDecoder> {
Music_Emu* emu; Music_Emu* emu;
id<CogSource> source; id<CogSource> source;
long sampleRate; double sampleRate;
long length; long length;
long fade; long fade;
NSString* codec; NSString* codec;

View File

@ -53,10 +53,15 @@ gme_err_t readCallback(void *data, void *out, int count) {
return NO; return NO;
} }
sampleRate = 44100; sampleRate = [[[[NSUserDefaultsController sharedUserDefaultsController] defaults] valueForKey:@"synthSampleRate"] doubleValue];
if(sampleRate < 8000.0) {
sampleRate = 44100.0;
} else if(sampleRate > 192000.0) {
sampleRate = 192000.0;
}
if(type == gme_spc_type || type == gme_sfm_type) if(type == gme_spc_type || type == gme_sfm_type)
sampleRate = 32000; sampleRate = 32000.0;
emu = gme_new_emu(type, (int)sampleRate); emu = gme_new_emu(type, (int)sampleRate);
if(!emu) { if(!emu) {
@ -109,16 +114,30 @@ gme_err_t readCallback(void *data, void *out, int count) {
length = info->length; length = info->length;
} else if(info->loop_length > 0) { } else if(info->loop_length > 0) {
DLog(@"Using loop length: %i", info->loop_length); DLog(@"Using loop length: %i", info->loop_length);
length = info->intro_length + 2 * info->loop_length; int loopCount = [[[[NSUserDefaultsController sharedUserDefaultsController] defaults] valueForKey:@"synthDefaultLoopCount"] intValue];
if(loopCount < 0) {
loopCount = 1;
} else if(loopCount > 10) {
loopCount = 10;
}
length = info->intro_length + loopCount * info->loop_length;
} else { } else {
length = 150000; double defaultLength = [[[[NSUserDefaultsController sharedUserDefaultsController] defaults] valueForKey:@"synthDefaultSeconds"] doubleValue];
if(defaultLength < 0) {
defaultLength = 150.0;
}
length = (int)ceil(defaultLength * 1000.0);
DLog(@"Setting default: %li", length); DLog(@"Setting default: %li", length);
} }
if(info->fade_length >= 0) { if(info->fade_length >= 0) {
fade = info->fade_length; fade = info->fade_length;
} else { } else {
fade = 8000; double defaultFade = [[[[NSUserDefaultsController sharedUserDefaultsController] defaults] valueForKey:@"synthDefaultFadeSeconds"] doubleValue];
if(defaultFade < 0) {
defaultFade = 0;
}
fade = (int)ceil(defaultFade * 1000.0);
} }
gme_free_info(info); gme_free_info(info);
@ -143,7 +162,7 @@ gme_err_t readCallback(void *data, void *out, int count) {
- (NSDictionary *)properties { - (NSDictionary *)properties {
return @{ @"bitrate": @(0), return @{ @"bitrate": @(0),
@"sampleRate": @(sampleRate), @"sampleRate": @(sampleRate),
@"totalFrames": @((long)(length * ((float)sampleRate * 0.001))), @"totalFrames": @((long)(length * (sampleRate * 0.001))),
@"bitsPerSample": @(sizeof(short) * 8), // Samples are short @"bitsPerSample": @(sizeof(short) * 8), // Samples are short
@"channels": @(2), // output from gme_play is in stereo @"channels": @(2), // output from gme_play is in stereo
@"seekable": @(YES), @"seekable": @(YES),
@ -176,7 +195,7 @@ gme_err_t readCallback(void *data, void *out, int count) {
- (long)seek:(long)frame { - (long)seek:(long)frame {
gme_err_t error; gme_err_t error;
error = gme_seek(emu, frame / 44.1); error = gme_seek(emu, frame * sampleRate * 0.001);
if(error) { if(error) {
return -1; return -1;
} }

View File

@ -1205,8 +1205,17 @@ static int usf_info(void *context, const char *name, const char *value) {
tagFadeMs = info.tag_fade_ms; tagFadeMs = info.tag_fade_ms;
if(!tagLengthMs) { if(!tagLengthMs) {
tagLengthMs = (2 * 60 + 30) * 1000; double defaultLength = [[[[NSUserDefaultsController sharedUserDefaultsController] defaults] valueForKey:@"synthDefaultSeconds"] doubleValue];
tagFadeMs = 8000; double defaultFade = [[[[NSUserDefaultsController sharedUserDefaultsController] defaults] valueForKey:@"synthDefaultFadeSeconds"] doubleValue];
if(defaultLength < 0) {
defaultLength = 150.0;
}
if(defaultFade < 0) {
defaultFade = 0;
}
tagLengthMs = (int)ceil(defaultLength * 1000.0);
tagFadeMs = (int)ceil(defaultFade * 1000.0);
} }
replayGainAlbumGain = info.albumGain; replayGainAlbumGain = info.albumGain;

View File

@ -17,6 +17,8 @@
int32_t *buffer; int32_t *buffer;
int trackNumber; int trackNumber;
double sampleRate;
long totalFrames; long totalFrames;
long framesLength; long framesLength;
long framesFade; long framesFade;

View File

@ -33,10 +33,17 @@ static void oneTimeInit(void) {
if(size > UINT_MAX) if(size > UINT_MAX)
return NO; return NO;
sampleRate = [[[[NSUserDefaultsController sharedUserDefaultsController] defaults] valueForKey:@"synthSampleRate"] doubleValue];
if(sampleRate < 8000.0) {
sampleRate = 44100.0;
} else if(sampleRate > 192000.0) {
sampleRate = 192000.0;
}
void *data = malloc(size); void *data = malloc(size);
[s read:data amount:size]; [s read:data amount:size];
tune = hvl_LoadTune(data, (uint32_t)size, 44100, 2); tune = hvl_LoadTune(data, (uint32_t)size, (int)sampleRate, 2);
free(data); free(data);
if(!tune) if(!tune)
return NO; return NO;
@ -62,14 +69,19 @@ static void oneTimeInit(void) {
++loops; ++loops;
} }
framesLength = tune->ht_PlayingTime * 44100 / (tune->ht_SpeedMultiplier * 50); double defaultFade = [[[[NSUserDefaultsController sharedUserDefaultsController] defaults] valueForKey:@"synthDefaultFadeSeconds"] doubleValue];
framesFade = 44100 * 8; if(defaultFade < 0.0) {
defaultFade = 0.0;
}
framesLength = tune->ht_PlayingTime * sampleRate / (tune->ht_SpeedMultiplier * 50);
framesFade = (int)ceil(sampleRate * defaultFade);
totalFrames = framesLength + framesFade; totalFrames = framesLength + framesFade;
framesRead = 0; framesRead = 0;
framesInBuffer = 0; framesInBuffer = 0;
buffer = malloc(sizeof(int32_t) * (44100 / 50) * 2); buffer = malloc(sizeof(int32_t) * ((int)ceil(sampleRate) / 50) * 2);
hvl_InitSubsong(tune, trackNumber); hvl_InitSubsong(tune, trackNumber);
@ -81,7 +93,7 @@ static void oneTimeInit(void) {
- (NSDictionary *)properties { - (NSDictionary *)properties {
return @{ @"bitrate": @(0), return @{ @"bitrate": @(0),
@"sampleRate": @(44100), @"sampleRate": @(sampleRate),
@"totalFrames": @(totalFrames), @"totalFrames": @(totalFrames),
@"bitsPerSample": @(32), @"bitsPerSample": @(32),
@"floatingPoint": @(YES), @"floatingPoint": @(YES),
@ -121,7 +133,7 @@ static void oneTimeInit(void) {
} }
} }
hvl_DecodeFrame(tune, (int8_t *)buffer, ((int8_t *)buffer) + 4, 8); hvl_DecodeFrame(tune, (int8_t *)buffer, ((int8_t *)buffer) + 4, 8);
framesInBuffer = 44100 / 50; framesInBuffer = (int)ceil(sampleRate / 50);
} }
if(!repeatone && framesRead + total > framesLength) { if(!repeatone && framesRead + total > framesLength) {
@ -156,7 +168,7 @@ static void oneTimeInit(void) {
while(framesRead < frame) { while(framesRead < frame) {
hvl_play_irq(tune); hvl_play_irq(tune);
framesRead += 44100 / 50; framesRead += (int)ceil(sampleRate / 50);
} }
return framesRead; return framesRead;

View File

@ -30,6 +30,8 @@ class BMPlayer;
BOOL soundFontsAssigned; BOOL soundFontsAssigned;
BOOL isLooped; BOOL isLooped;
double sampleRate;
long totalFrames; long totalFrames;
long framesLength; long framesLength;
long framesFade; long framesFade;

View File

@ -46,6 +46,13 @@ static OSType getOSType(const char *in_) {
return NO; return NO;
} }
sampleRate = [[[[NSUserDefaultsController sharedUserDefaultsController] defaults] valueForKey:@"synthSampleRate"] doubleValue];
if(sampleRate < 8000.0) {
sampleRate = 44100.0;
} else if(sampleRate > 192000.0) {
sampleRate = 192000.0;
}
source = s; source = s;
std::vector<uint8_t> file_data; std::vector<uint8_t> file_data;
@ -76,8 +83,12 @@ static OSType getOSType(const char *in_) {
if(loopStart != 0 || loopEnd != framesLength) { if(loopStart != 0 || loopEnd != framesLength) {
// two loops and a fade // two loops and a fade
double defaultFade = [[[[NSUserDefaultsController sharedUserDefaultsController] defaults] valueForKey:@"synthDefaultFadeSeconds"] doubleValue];
if(defaultFade < 0.0) {
defaultFade = 0.0;
}
framesLength = loopStart + (loopEnd - loopStart) * 2; framesLength = loopStart + (loopEnd - loopStart) * 2;
framesFade = 8000; framesFade = (int)ceil(defaultFade * 1000.0);
isLooped = YES; isLooped = YES;
} else { } else {
framesLength += 1000; framesLength += 1000;
@ -85,8 +96,8 @@ static OSType getOSType(const char *in_) {
isLooped = NO; isLooped = NO;
} }
framesLength = framesLength * 441 / 10; framesLength = (int)ceil(framesLength * sampleRate * 0.001);
framesFade = framesFade * 441 / 10; framesFade = (int)ceil(framesFade * sampleRate * 0.001);
totalFrames = framesLength + framesFade; totalFrames = framesLength + framesFade;
@ -100,7 +111,7 @@ static OSType getOSType(const char *in_) {
- (NSDictionary *)properties { - (NSDictionary *)properties {
return @{ @"bitrate": @(0), return @{ @"bitrate": @(0),
@"sampleRate": @(44100), @"sampleRate": @(sampleRate),
@"totalFrames": @(totalFrames), @"totalFrames": @(totalFrames),
@"bitsPerSample": @(32), @"bitsPerSample": @(32),
@"floatingPoint": @(YES), @"floatingPoint": @(YES),
@ -203,7 +214,7 @@ static OSType getOSType(const char *in_) {
resamplingSinc = true; resamplingSinc = true;
bmplayer->setSincInterpolation(resamplingSinc); bmplayer->setSincInterpolation(resamplingSinc);
bmplayer->setSampleRate(44100); bmplayer->setSampleRate(sampleRate);
if([soundFontPath length]) if([soundFontPath length])
bmplayer->setFileSoundFont([soundFontPath UTF8String]); bmplayer->setFileSoundFont([soundFontPath UTF8String]);
@ -219,7 +230,7 @@ static OSType getOSType(const char *in_) {
msplayer->set_extp(1); msplayer->set_extp(1);
msplayer->setSampleRate(44100); msplayer->setSampleRate(sampleRate);
} else if([[plugin substringToIndex:5] isEqualToString:@"OPL3W"]) { } else if([[plugin substringToIndex:5] isEqualToString:@"OPL3W"]) {
MSPlayer *msplayer = new MSPlayer; MSPlayer *msplayer = new MSPlayer;
player = msplayer; player = msplayer;
@ -230,7 +241,7 @@ static OSType getOSType(const char *in_) {
msplayer->set_extp(1); msplayer->set_extp(1);
msplayer->setSampleRate(44100); msplayer->setSampleRate(sampleRate);
} else { } else {
const char *cplugin = [plugin UTF8String]; const char *cplugin = [plugin UTF8String];
OSType componentSubType; OSType componentSubType;
@ -243,7 +254,7 @@ static OSType getOSType(const char *in_) {
auplayer = new AUPlayer; auplayer = new AUPlayer;
auplayer->setComponent(componentSubType, componentManufacturer); auplayer->setComponent(componentSubType, componentManufacturer);
auplayer->setSampleRate(44100); auplayer->setSampleRate(sampleRate);
if([soundFontPath length]) { if([soundFontPath length]) {
auplayer->setSoundFont([soundFontPath UTF8String]); auplayer->setSoundFont([soundFontPath UTF8String]);

View File

@ -7,6 +7,7 @@
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
833A899C286FF3150022E036 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 833A899B286FF3150022E036 /* Cocoa.framework */; };
83747C1A2862DB2F0021245F /* Shared.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 83747C182862DB2F0021245F /* Shared.xcconfig */; }; 83747C1A2862DB2F0021245F /* Shared.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 83747C182862DB2F0021245F /* Shared.xcconfig */; };
83E5FE731FFF010C00659F0F /* OMPTDecoder.mm in Sources */ = {isa = PBXBuildFile; fileRef = 83E5FE6D1FFF010B00659F0F /* OMPTDecoder.mm */; }; 83E5FE731FFF010C00659F0F /* OMPTDecoder.mm in Sources */ = {isa = PBXBuildFile; fileRef = 83E5FE6D1FFF010B00659F0F /* OMPTDecoder.mm */; };
83E5FE741FFF010C00659F0F /* OMPTContainer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 83E5FE6F1FFF010B00659F0F /* OMPTContainer.mm */; }; 83E5FE741FFF010C00659F0F /* OMPTContainer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 83E5FE6F1FFF010B00659F0F /* OMPTContainer.mm */; };
@ -47,6 +48,7 @@
/* End PBXCopyFilesBuildPhase section */ /* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
833A899B286FF3150022E036 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
83747C182862DB2F0021245F /* Shared.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Shared.xcconfig; sourceTree = "<group>"; }; 83747C182862DB2F0021245F /* Shared.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Shared.xcconfig; sourceTree = "<group>"; };
83E5EFA31FFEF78100659F0F /* OpenMPT.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OpenMPT.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; 83E5EFA31FFEF78100659F0F /* OpenMPT.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OpenMPT.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
83E5EFA61FFEF78100659F0F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 83E5EFA61FFEF78100659F0F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@ -67,6 +69,7 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
833A899C286FF3150022E036 /* Cocoa.framework in Frameworks */,
83F30AE8286EBD2A0005EF06 /* libOpenMPT.framework in Frameworks */, 83F30AE8286EBD2A0005EF06 /* libOpenMPT.framework in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
@ -113,6 +116,7 @@
83E5EFB21FFEF79000659F0F /* Frameworks */ = { 83E5EFB21FFEF79000659F0F /* Frameworks */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
833A899B286FF3150022E036 /* Cocoa.framework */,
83F30A81286EBB420005EF06 /* libOpenMPT.xcodeproj */, 83F30A81286EBB420005EF06 /* libOpenMPT.xcodeproj */,
); );
name = Frameworks; name = Frameworks;

View File

@ -19,6 +19,8 @@
id<CogSource> source; id<CogSource> source;
long length; long length;
double sampleRate;
} }
- (void)setSource:(id<CogSource>)s; - (void)setSource:(id<CogSource>)s;

View File

@ -39,6 +39,13 @@ static void g_push_archive_extensions(std::vector<std::string> &list) {
long size = [source tell]; long size = [source tell];
[source seek:0 whence:SEEK_SET]; [source seek:0 whence:SEEK_SET];
sampleRate = [[[[NSUserDefaultsController sharedUserDefaultsController] defaults] valueForKey:@"synthSampleRate"] doubleValue];
if(sampleRate < 8000.0) {
sampleRate = 44100.0;
} else if(sampleRate > 192000.0) {
sampleRate = 192000.0;
}
std::vector<char> data(static_cast<std::size_t>(size)); std::vector<char> data(static_cast<std::size_t>(size));
[source read:data.data() amount:size]; [source read:data.data() amount:size];
@ -71,7 +78,7 @@ static void g_push_archive_extensions(std::vector<std::string> &list) {
mod->select_subsong(track_num); mod->select_subsong(track_num);
length = mod->get_duration_seconds() * 44100.0; length = mod->get_duration_seconds() * sampleRate;
mod->set_repeat_count(IsRepeatOneSet() ? -1 : 0); mod->set_repeat_count(IsRepeatOneSet() ? -1 : 0);
mod->set_render_param(openmpt::module::RENDER_MASTERGAIN_MILLIBEL, 0); mod->set_render_param(openmpt::module::RENDER_MASTERGAIN_MILLIBEL, 0);
@ -91,7 +98,7 @@ static void g_push_archive_extensions(std::vector<std::string> &list) {
- (NSDictionary *)properties { - (NSDictionary *)properties {
return @{ @"bitrate": @(0), return @{ @"bitrate": @(0),
@"sampleRate": @(44100), @"sampleRate": @(sampleRate),
@"totalFrames": @(length), @"totalFrames": @(length),
@"bitsPerSample": @(32), @"bitsPerSample": @(32),
@"floatingPoint": @(YES), @"floatingPoint": @(YES),
@ -114,7 +121,7 @@ static void g_push_archive_extensions(std::vector<std::string> &list) {
if(framesToRender > frames) if(framesToRender > frames)
framesToRender = frames; framesToRender = frames;
std::size_t count = mod->read_interleaved_stereo(44100, framesToRender, ((float *)buf) + total * 2); std::size_t count = mod->read_interleaved_stereo(sampleRate, framesToRender, ((float *)buf) + total * 2);
if(count == 0) if(count == 0)
break; break;
@ -128,7 +135,7 @@ static void g_push_archive_extensions(std::vector<std::string> &list) {
} }
- (long)seek:(long)frame { - (long)seek:(long)frame {
mod->set_position_seconds(frame * (1.0 / 44100.0)); mod->set_position_seconds(frame / sampleRate);
return frame; return frame;
} }

View File

@ -19,6 +19,9 @@
DATA_LOADER* dLoad; DATA_LOADER* dLoad;
PlayerA* mainPlr; PlayerA* mainPlr;
id<CogSource> source; id<CogSource> source;
double sampleRate;
long loopCount;
double fadeTime;
long length; long length;
BOOL trackEnded; BOOL trackEnded;
} }

View File

@ -88,7 +88,6 @@ static void PlayerLogCallback(void* userParam, PlayerBase* player, UINT8 level,
return; return;
} }
const int sampleRate = 44100;
const int numChannels = 2; const int numChannels = 2;
const int numBitsPerSample = 24; const int numBitsPerSample = 24;
const int smplAlloc = 2048; const int smplAlloc = 2048;
@ -112,8 +111,24 @@ const int masterVol = 0x10000; // Fixed point 16.16
return NO; return NO;
} }
sampleRate = [[[[NSUserDefaultsController sharedUserDefaultsController] defaults] valueForKey:@"synthSampleRate"] doubleValue];
if(sampleRate < 8000.0) {
sampleRate = 44100.0;
} else if(sampleRate > 192000.0) {
sampleRate = 192000.0;
}
loopCount = [[[[NSUserDefaultsController sharedUserDefaultsController] defaults] valueForKey:@"synthDefaultLoopCount"] longValue];
if(loopCount < 1) {
loopCount = 1;
} else if(loopCount > 10) {
loopCount = 10;
}
fadeTime = [[[[NSUserDefaultsController sharedUserDefaultsController] defaults] valueForKey:@"synthDefaultFadeSeconds"] doubleValue];
BOOL repeatOne = IsRepeatOneSet(); BOOL repeatOne = IsRepeatOneSet();
uint32_t maxLoops = repeatOne ? 0 : 2; uint32_t maxLoops = repeatOne ? 0 : (uint32_t)loopCount;
mainPlr = new PlayerA; mainPlr = new PlayerA;
mainPlr->RegisterPlayerEngine(new VGMPlayer); mainPlr->RegisterPlayerEngine(new VGMPlayer);
@ -127,12 +142,12 @@ const int masterVol = 0x10000; // Fixed point 16.16
PlayerA::Config pCfg = mainPlr->GetConfiguration(); PlayerA::Config pCfg = mainPlr->GetConfiguration();
pCfg.masterVol = masterVol; pCfg.masterVol = masterVol;
pCfg.loopCount = maxLoops; pCfg.loopCount = maxLoops;
pCfg.fadeSmpls = sampleRate * 4; // fade over 4 seconds pCfg.fadeSmpls = (int)ceil(sampleRate * fadeTime); // fade over configured duration
pCfg.endSilenceSmpls = sampleRate / 2; // 0.5 seconds of silence at the end pCfg.endSilenceSmpls = sampleRate / 2; // 0.5 seconds of silence at the end
pCfg.pbSpeed = 1.0; pCfg.pbSpeed = 1.0;
mainPlr->SetConfiguration(pCfg); mainPlr->SetConfiguration(pCfg);
} }
mainPlr->SetOutputSettings(sampleRate, numChannels, numBitsPerSample, smplAlloc); mainPlr->SetOutputSettings((int)ceil(sampleRate), numChannels, numBitsPerSample, smplAlloc);
[source seek:0 whence:SEEK_END]; [source seek:0 whence:SEEK_END];
size_t size = [source tell]; size_t size = [source tell];
@ -198,7 +213,7 @@ const int masterVol = 0x10000; // Fixed point 16.16
return 0; return 0;
BOOL repeatOne = IsRepeatOneSet(); BOOL repeatOne = IsRepeatOneSet();
uint32_t maxLoops = repeatOne ? 0 : 2; uint32_t maxLoops = repeatOne ? 0 : (uint32_t)loopCount;
PlayerBase* player = mainPlr->GetPlayer(); PlayerBase* player = mainPlr->GetPlayer();
mainPlr->SetLoopCount(maxLoops); mainPlr->SetLoopCount(maxLoops);

View File

@ -29,6 +29,8 @@
NSString *currentUrl; NSString *currentUrl;
BOOL hintAdded; BOOL hintAdded;
double sampleRate;
int n_channels; int n_channels;
long renderedTotal; long renderedTotal;

View File

@ -166,6 +166,13 @@ static void sidTuneLoader(const char *fileName, std::vector<uint8_t> &bufferRef)
[self setSource:s]; [self setSource:s];
sampleRate = [[[[NSUserDefaultsController sharedUserDefaultsController] defaults] valueForKey:@"synthSampleRate"] doubleValue];
if(sampleRate < 8000.0) {
sampleRate = 44100.0;
} else if(sampleRate > 192000.0) {
sampleRate = 192000.0;
}
NSString *path = [[s url] absoluteString]; NSString *path = [[s url] absoluteString];
NSRange fragmentRange = [path rangeOfString:@"#" options:NSBackwardsSearch]; NSRange fragmentRange = [path rangeOfString:@"#" options:NSBackwardsSearch];
if(fragmentRange.location != NSNotFound) { if(fragmentRange.location != NSNotFound) {
@ -195,7 +202,9 @@ static void sidTuneLoader(const char *fileName, std::vector<uint8_t> &bufferRef)
n_channels = 1; n_channels = 1;
length = 3 * 60 * 44100; double defaultLength = [[[[NSUserDefaultsController sharedUserDefaultsController] defaults] valueForKey:@"synthDefaultSeconds"] doubleValue];
length = (int)ceil(sampleRate * defaultLength);
tune->selectSong(track_num); tune->selectSong(track_num);
@ -224,7 +233,7 @@ static void sidTuneLoader(const char *fileName, std::vector<uint8_t> &bufferRef)
const SidTuneInfo *tuneInfo = tune->getInfo(); const SidTuneInfo *tuneInfo = tune->getInfo();
SidConfig conf = engine->config(); SidConfig conf = engine->config();
conf.frequency = 44100; conf.frequency = (int)ceil(sampleRate);
conf.sidEmulation = builder; conf.sidEmulation = builder;
conf.playback = SidConfig::MONO; conf.playback = SidConfig::MONO;
if(tuneInfo && (tuneInfo->sidChips() > 1)) if(tuneInfo && (tuneInfo->sidChips() > 1))
@ -236,8 +245,13 @@ static void sidTuneLoader(const char *fileName, std::vector<uint8_t> &bufferRef)
n_channels = 2; n_channels = 2;
} }
double defaultFade = [[[[NSUserDefaultsController sharedUserDefaultsController] defaults] valueForKey:@"synthDefaultFadeSeconds"] doubleValue];
if(defaultFade < 0.0) {
defaultFade = 0.0;
}
renderedTotal = 0; renderedTotal = 0;
fadeTotal = fadeRemain = 44100 * 8; fadeTotal = fadeRemain = (int)ceil(sampleRate * defaultFade);
[self willChangeValueForKey:@"properties"]; [self willChangeValueForKey:@"properties"];
[self didChangeValueForKey:@"properties"]; [self didChangeValueForKey:@"properties"];
@ -247,7 +261,7 @@ static void sidTuneLoader(const char *fileName, std::vector<uint8_t> &bufferRef)
- (NSDictionary *)properties { - (NSDictionary *)properties {
return @{ @"bitrate": @(0), return @{ @"bitrate": @(0),
@"sampleRate": @(44100), @"sampleRate": @(sampleRate),
@"totalFrames": @(length), @"totalFrames": @(length),
@"bitsPerSample": @(16), @"bitsPerSample": @(16),
@"floatingPoint": @(NO), @"floatingPoint": @(NO),

View File

@ -10,6 +10,7 @@
8314D8091A35654900EEE8E6 /* SidDecoder.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8314D8041A35654900EEE8E6 /* SidDecoder.mm */; }; 8314D8091A35654900EEE8E6 /* SidDecoder.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8314D8041A35654900EEE8E6 /* SidDecoder.mm */; };
8314D80A1A35654900EEE8E6 /* SidMetadataReader.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8314D8061A35654900EEE8E6 /* SidMetadataReader.mm */; }; 8314D80A1A35654900EEE8E6 /* SidMetadataReader.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8314D8061A35654900EEE8E6 /* SidMetadataReader.mm */; };
8314D80B1A35654900EEE8E6 /* SidContainer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8314D8081A35654900EEE8E6 /* SidContainer.mm */; }; 8314D80B1A35654900EEE8E6 /* SidContainer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8314D8081A35654900EEE8E6 /* SidContainer.mm */; };
833A8998286FF2E30022E036 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 833A8996286FF2E30022E036 /* Cocoa.framework */; };
836F5BEC1A357915002730CC /* roms.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 836F5BEA1A357915002730CC /* roms.cpp */; }; 836F5BEC1A357915002730CC /* roms.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 836F5BEA1A357915002730CC /* roms.cpp */; };
83747C012862DA420021245F /* Shared.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 83747BFF2862DA420021245F /* Shared.xcconfig */; }; 83747C012862DA420021245F /* Shared.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 83747BFF2862DA420021245F /* Shared.xcconfig */; };
EDBE911825E7EA01001EB4A4 /* sidplayfp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDBE8F0F25E7E74D001EB4A4 /* sidplayfp.framework */; }; EDBE911825E7EA01001EB4A4 /* sidplayfp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDBE8F0F25E7E74D001EB4A4 /* sidplayfp.framework */; };
@ -51,6 +52,7 @@
8314D80C1A35657700EEE8E6 /* Plugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Plugin.h; path = ../../../Audio/Plugin.h; sourceTree = "<group>"; }; 8314D80C1A35657700EEE8E6 /* Plugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Plugin.h; path = ../../../Audio/Plugin.h; sourceTree = "<group>"; };
8314D80D1A35658C00EEE8E6 /* Logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Logging.h; path = ../../../Utils/Logging.h; sourceTree = "<group>"; }; 8314D80D1A35658C00EEE8E6 /* Logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Logging.h; path = ../../../Utils/Logging.h; sourceTree = "<group>"; };
8314D80E1A3565AC00EEE8E6 /* PlaylistController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PlaylistController.h; path = ../../../Playlist/PlaylistController.h; sourceTree = "<group>"; }; 8314D80E1A3565AC00EEE8E6 /* PlaylistController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PlaylistController.h; path = ../../../Playlist/PlaylistController.h; sourceTree = "<group>"; };
833A8996286FF2E30022E036 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
836F5BEA1A357915002730CC /* roms.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = roms.cpp; sourceTree = SOURCE_ROOT; }; 836F5BEA1A357915002730CC /* roms.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = roms.cpp; sourceTree = SOURCE_ROOT; };
836F5BEB1A357915002730CC /* roms.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = roms.hpp; sourceTree = SOURCE_ROOT; }; 836F5BEB1A357915002730CC /* roms.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = roms.hpp; sourceTree = SOURCE_ROOT; };
83747BFF2862DA420021245F /* Shared.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Shared.xcconfig; sourceTree = "<group>"; }; 83747BFF2862DA420021245F /* Shared.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Shared.xcconfig; sourceTree = "<group>"; };
@ -62,6 +64,7 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
833A8998286FF2E30022E036 /* Cocoa.framework in Frameworks */,
EDBE911825E7EA01001EB4A4 /* sidplayfp.framework in Frameworks */, EDBE911825E7EA01001EB4A4 /* sidplayfp.framework in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
@ -117,6 +120,7 @@
8314D64A1A354E4400EEE8E6 /* Frameworks */ = { 8314D64A1A354E4400EEE8E6 /* Frameworks */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
833A8996286FF2E30022E036 /* Cocoa.framework */,
EDBE8F0A25E7E74D001EB4A4 /* sidplayfp.xcodeproj */, EDBE8F0A25E7E74D001EB4A4 /* sidplayfp.xcodeproj */,
); );
name = Frameworks; name = Frameworks;

View File

@ -30,6 +30,8 @@
BOOL playForever; BOOL playForever;
BOOL canPlayForever; BOOL canPlayForever;
int loopCount;
double fadeTime;
int sampleRate; int sampleRate;
int channels; int channels;
int bitrate; int bitrate;

View File

@ -234,6 +234,18 @@ static NSString *get_description_tag(const char *description, const char *tag, c
- (BOOL)open:(id<CogSource>)s { - (BOOL)open:(id<CogSource>)s {
int track_num = [[[s url] fragment] intValue]; int track_num = [[[s url] fragment] intValue];
loopCount = [[[[NSUserDefaultsController sharedUserDefaultsController] defaults] valueForKey:@"synthDefaultLoopCount"] intValue];
if(loopCount < 1) {
loopCount = 1;
} else if(loopCount > 10) {
loopCount = 10;
}
fadeTime = [[[[NSUserDefaultsController sharedUserDefaultsController] defaults] valueForKey:@"synthDefaultFadeTime"] doubleValue];
if(fadeTime < 0.0) {
fadeTime = 0.0;
}
NSString *path = [[s url] absoluteString]; NSString *path = [[s url] absoluteString];
NSRange fragmentRange = [path rangeOfString:@"#" options:NSBackwardsSearch]; NSRange fragmentRange = [path rangeOfString:@"#" options:NSBackwardsSearch];
if(fragmentRange.location != NSNotFound) { if(fragmentRange.location != NSNotFound) {
@ -262,8 +274,8 @@ static NSString *get_description_tag(const char *description, const char *tag, c
vcfg.allow_play_forever = 1; vcfg.allow_play_forever = 1;
vcfg.play_forever = playForever; vcfg.play_forever = playForever;
vcfg.loop_count = 2; vcfg.loop_count = loopCount;
vcfg.fade_time = 10; vcfg.fade_time = fadeTime;
vcfg.fade_delay = 0; vcfg.fade_delay = 0;
vcfg.ignore_loop = 0; vcfg.ignore_loop = 0;

View File

@ -611,11 +611,11 @@
<point key="canvasLocation" x="450" y="183"/> <point key="canvasLocation" x="450" y="183"/>
</customView> </customView>
<customView wantsLayer="YES" id="JXu-ar-J3Y" userLabel="MIDIView"> <customView wantsLayer="YES" id="JXu-ar-J3Y" userLabel="MIDIView">
<rect key="frame" x="0.0" y="0.0" width="530" height="140"/> <rect key="frame" x="0.0" y="0.0" width="530" height="244"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews> <subviews>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="SBO-WF-DVS" userLabel="Push Button - Select a SoundFont"> <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="SBO-WF-DVS" userLabel="Push Button - Select a SoundFont">
<rect key="frame" x="15" y="98" width="160" height="32"/> <rect key="frame" x="15" y="202" width="160" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Select a SoundFont" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="yeL-9c-lFq" userLabel="Button Cell - Select a SoundFont"> <buttonCell key="cell" type="push" title="Select a SoundFont" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="yeL-9c-lFq" userLabel="Button Cell - Select a SoundFont">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
@ -626,7 +626,7 @@
</connections> </connections>
</button> </button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="FRC-Dh-BS2" userLabel="Text Field - Selected:"> <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="FRC-Dh-BS2" userLabel="Text Field - Selected:">
<rect key="frame" x="174" y="107" width="95" height="17"/> <rect key="frame" x="174" y="211" width="95" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Selected:" id="KJz-qS-IcO" userLabel="Text Field Cell - Selected"> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Selected:" id="KJz-qS-IcO" userLabel="Text Field Cell - Selected">
<font key="font" metaFont="system"/> <font key="font" metaFont="system"/>
@ -635,7 +635,7 @@
</textFieldCell> </textFieldCell>
</textField> </textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="cZr-2d-6cv"> <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="cZr-2d-6cv">
<rect key="frame" x="273" y="107" width="239" height="17"/> <rect key="frame" x="273" y="211" width="239" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Label" id="ECB-P0-pve"> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Label" id="ECB-P0-pve">
<font key="font" metaFont="system"/> <font key="font" metaFont="system"/>
@ -652,7 +652,7 @@
</textFieldCell> </textFieldCell>
</textField> </textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="G86-18-hiK"> <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="G86-18-hiK">
<rect key="frame" x="20" y="47" width="150" height="17"/> <rect key="frame" x="18" y="151" width="152" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Resampling Quality:" id="eX0-PC-iVo"> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Resampling Quality:" id="eX0-PC-iVo">
<font key="font" metaFont="system"/> <font key="font" metaFont="system"/>
@ -661,7 +661,7 @@
</textFieldCell> </textFieldCell>
</textField> </textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="4uG-vW-B64"> <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="4uG-vW-B64">
<rect key="frame" x="18" y="78" width="152" height="17"/> <rect key="frame" x="18" y="182" width="152" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="MIDI Plugin:" id="n5F-dq-NZh"> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="MIDI Plugin:" id="n5F-dq-NZh">
<font key="font" metaFont="system"/> <font key="font" metaFont="system"/>
@ -670,7 +670,7 @@
</textFieldCell> </textFieldCell>
</textField> </textField>
<popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="8Nj-G4-5ag"> <popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="8Nj-G4-5ag">
<rect key="frame" x="173" y="72" width="341" height="26"/> <rect key="frame" x="173" y="176" width="341" height="26"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<popUpButtonCell key="cell" type="push" title="Item 1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="vaQ-pZ-jXy" id="xcv-1b-kTI"> <popUpButtonCell key="cell" type="push" title="Item 1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="vaQ-pZ-jXy" id="xcv-1b-kTI">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/> <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
@ -691,7 +691,7 @@
</connections> </connections>
</popUpButton> </popUpButton>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="K5c-km-7Qa"> <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="K5c-km-7Qa">
<rect key="frame" x="20" y="16" width="150" height="17"/> <rect key="frame" x="20" y="120" width="150" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="MIDI Flavor:" id="FQF-vJ-hBx"> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="MIDI Flavor:" id="FQF-vJ-hBx">
<font key="font" metaFont="system"/> <font key="font" metaFont="system"/>
@ -700,7 +700,7 @@
</textFieldCell> </textFieldCell>
</textField> </textField>
<popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="1Yw-25-Gbs"> <popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="1Yw-25-Gbs">
<rect key="frame" x="173" y="10" width="341" height="26"/> <rect key="frame" x="173" y="114" width="341" height="26"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<popUpButtonCell key="cell" type="push" title="Item 1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" autoenablesItems="NO" altersStateOfSelectedItem="NO" selectedItem="XzK-h2-vIT" id="qzt-Ox-taI"> <popUpButtonCell key="cell" type="push" title="Item 1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" autoenablesItems="NO" altersStateOfSelectedItem="NO" selectedItem="XzK-h2-vIT" id="qzt-Ox-taI">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/> <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
@ -721,7 +721,7 @@
</connections> </connections>
</popUpButton> </popUpButton>
<popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="E1D-Bo-ZVf"> <popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="E1D-Bo-ZVf">
<rect key="frame" x="173" y="41" width="341" height="26"/> <rect key="frame" x="173" y="145" width="341" height="26"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<popUpButtonCell key="cell" type="push" title="Item 1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="3Gx-cs-3B0" id="5q7-83-7V6"> <popUpButtonCell key="cell" type="push" title="Item 1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="3Gx-cs-3B0" id="5q7-83-7V6">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/> <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
@ -741,8 +741,138 @@
<binding destination="52" name="selectedObject" keyPath="values.resampling" previousBinding="KxI-52-0UK" id="wsy-tb-NFy"/> <binding destination="52" name="selectedObject" keyPath="values.resampling" previousBinding="KxI-52-0UK" id="wsy-tb-NFy"/>
</connections> </connections>
</popUpButton> </popUpButton>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Ygc-nv-ZkO">
<rect key="frame" x="18" y="94" width="152" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" alignment="right" title="Default play time:" id="AQZ-ku-F8u">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="l3L-N5-gU1">
<rect key="frame" x="176" y="91" width="96" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" drawsBackground="YES" id="Isi-54-78h">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="52" name="value" keyPath="values.synthDefaultSeconds" id="6aS-7t-Otv">
<dictionary key="options">
<string key="NSValueTransformerName">TimeIntervalToStringTransformer</string>
</dictionary>
</binding>
</connections>
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="HDu-ff-N3s">
<rect key="frame" x="176" y="65" width="96" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" drawsBackground="YES" id="9Hu-FG-spW">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="52" name="value" keyPath="values.synthDefaultFadeSeconds" id="4mn-az-iz7">
<dictionary key="options">
<string key="NSValueTransformerName">TimeIntervalToStringTransformer</string>
</dictionary>
</binding>
</connections>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="JmH-HM-zwz">
<rect key="frame" x="276" y="94" width="91" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="hh:mm:ss.ms" id="klv-Wh-0ur">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="qhe-ea-0bx">
<rect key="frame" x="18" y="68" width="152" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" alignment="right" title="Default fade time:" id="UdW-qd-A0x">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="eyL-LI-NzO">
<rect key="frame" x="276" y="68" width="91" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="hh:mm:ss.ms" id="zaI-0m-tQf">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="4PD-ys-Cfu">
<rect key="frame" x="18" y="42" width="152" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" alignment="right" title="Default loop count:" id="Fgm-Vs-tgU">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="FX5-Lt-csQ">
<rect key="frame" x="176" y="39" width="96" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="v5P-kg-a0v">
<numberFormatter key="formatter" formatterBehavior="default10_4" numberStyle="decimal" formatWidth="-1" minimumIntegerDigits="1" maximumIntegerDigits="2000000000" maximumFractionDigits="3" id="Bii-6P-aHq"/>
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="52" name="value" keyPath="values.synthDefaultLoopCount" id="h30-gW-yrc"/>
</connections>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="8jM-zP-FSb">
<rect key="frame" x="276" y="42" width="228" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="(will be preferred if possible)" id="POG-ai-6D2">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Rrf-kn-YnS">
<rect key="frame" x="18" y="15" width="152" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" alignment="right" title="Sample rate:" id="A9I-fr-vHp">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="CiQ-nY-YXA">
<rect key="frame" x="176" y="12" width="96" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="h3A-Br-Gyc">
<numberFormatter key="formatter" formatterBehavior="default10_4" numberStyle="decimal" formatWidth="-1" minimumIntegerDigits="1" maximumIntegerDigits="2000000000" maximumFractionDigits="3" id="btb-qT-AIL"/>
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="52" name="value" keyPath="values.synthSampleRate" id="C52-5h-iFA"/>
</connections>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="esA-Kb-zTw">
<rect key="frame" x="276" y="15" width="70" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Hz" id="0Am-5Y-EKq">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews> </subviews>
<point key="canvasLocation" x="450" y="339"/> <point key="canvasLocation" x="450" y="391"/>
</customView> </customView>
<arrayController objectClassName="NSDictionary" editable="NO" id="JB6-r9-XpG" userLabel="ResamplerBehavior" customClass="ResamplerBehaviorArrayController"> <arrayController objectClassName="NSDictionary" editable="NO" id="JB6-r9-XpG" userLabel="ResamplerBehavior" customClass="ResamplerBehaviorArrayController">
<declaredKeys> <declaredKeys>

View File

@ -9,6 +9,7 @@
#import "GeneralPreferencesPlugin.h" #import "GeneralPreferencesPlugin.h"
#import "ColorToValueTransformer.h" #import "ColorToValueTransformer.h"
#import "PathToFileTransformer.h" #import "PathToFileTransformer.h"
#import "TimeIntervalToStringTransformer.h"
@implementation GeneralPreferencesPlugin @implementation GeneralPreferencesPlugin
@ -20,6 +21,10 @@
NSValueTransformer *colorToValueTransformer = [[ColorToValueTransformer alloc] init]; NSValueTransformer *colorToValueTransformer = [[ColorToValueTransformer alloc] init];
[NSValueTransformer setValueTransformer:colorToValueTransformer [NSValueTransformer setValueTransformer:colorToValueTransformer
forName:@"ColorToValueTransformer"]; forName:@"ColorToValueTransformer"];
NSValueTransformer *timeIntervalToStringTransformer = [[TimeIntervalToStringTransformer alloc] init];
[NSValueTransformer setValueTransformer:timeIntervalToStringTransformer
forName:@"TimeIntervalToStringTransformer"];
} }
+ (NSArray *)preferencePanes { + (NSArray *)preferencePanes {

View File

@ -22,6 +22,7 @@
8307D31728606EAF000FF8EB /* growl@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 8307D31328606EAF000FF8EB /* growl@2x.png */; }; 8307D31728606EAF000FF8EB /* growl@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 8307D31328606EAF000FF8EB /* growl@2x.png */; };
8307D31828606EAF000FF8EB /* general.png in Resources */ = {isa = PBXBuildFile; fileRef = 8307D31428606EAF000FF8EB /* general.png */; }; 8307D31828606EAF000FF8EB /* general.png in Resources */ = {isa = PBXBuildFile; fileRef = 8307D31428606EAF000FF8EB /* general.png */; };
8307D31928606EAF000FF8EB /* growl.png in Resources */ = {isa = PBXBuildFile; fileRef = 8307D31528606EAF000FF8EB /* growl.png */; }; 8307D31928606EAF000FF8EB /* growl.png in Resources */ = {isa = PBXBuildFile; fileRef = 8307D31528606EAF000FF8EB /* growl.png */; };
833A899F286FF3850022E036 /* TimeIntervalToStringTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 833A899E286FF3850022E036 /* TimeIntervalToStringTransformer.m */; };
83651DA527322C8700A2C097 /* MIDIFlavorBehaviorArrayController.m in Sources */ = {isa = PBXBuildFile; fileRef = 83651DA327322C8700A2C097 /* MIDIFlavorBehaviorArrayController.m */; }; 83651DA527322C8700A2C097 /* MIDIFlavorBehaviorArrayController.m in Sources */ = {isa = PBXBuildFile; fileRef = 83651DA327322C8700A2C097 /* MIDIFlavorBehaviorArrayController.m */; };
8372053718E3DEAF007EFAD4 /* ResamplerBehaviorArrayController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8372053618E3DEAF007EFAD4 /* ResamplerBehaviorArrayController.m */; }; 8372053718E3DEAF007EFAD4 /* ResamplerBehaviorArrayController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8372053618E3DEAF007EFAD4 /* ResamplerBehaviorArrayController.m */; };
837C0D401C50954000CAE18F /* MIDIPluginBehaviorArrayController.m in Sources */ = {isa = PBXBuildFile; fileRef = 837C0D3F1C50954000CAE18F /* MIDIPluginBehaviorArrayController.m */; }; 837C0D401C50954000CAE18F /* MIDIPluginBehaviorArrayController.m in Sources */ = {isa = PBXBuildFile; fileRef = 837C0D3F1C50954000CAE18F /* MIDIPluginBehaviorArrayController.m */; };
@ -102,6 +103,8 @@
8307D31328606EAF000FF8EB /* growl@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "growl@2x.png"; path = "Icons/growl@2x.png"; sourceTree = "<group>"; }; 8307D31328606EAF000FF8EB /* growl@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "growl@2x.png"; path = "Icons/growl@2x.png"; sourceTree = "<group>"; };
8307D31428606EAF000FF8EB /* general.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = general.png; path = Icons/general.png; sourceTree = "<group>"; }; 8307D31428606EAF000FF8EB /* general.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = general.png; path = Icons/general.png; sourceTree = "<group>"; };
8307D31528606EAF000FF8EB /* growl.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = growl.png; path = Icons/growl.png; sourceTree = "<group>"; }; 8307D31528606EAF000FF8EB /* growl.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = growl.png; path = Icons/growl.png; sourceTree = "<group>"; };
833A899D286FF3850022E036 /* TimeIntervalToStringTransformer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TimeIntervalToStringTransformer.h; sourceTree = "<group>"; };
833A899E286FF3850022E036 /* TimeIntervalToStringTransformer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TimeIntervalToStringTransformer.m; sourceTree = "<group>"; };
833F681B1CDBCAA700AFB9F0 /* es */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/InfoPlist.strings; sourceTree = "<group>"; }; 833F681B1CDBCAA700AFB9F0 /* es */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/InfoPlist.strings; sourceTree = "<group>"; };
833F681C1CDBCAA700AFB9F0 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = "<group>"; }; 833F681C1CDBCAA700AFB9F0 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = "<group>"; };
8347435D20E6D58800063D45 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Preferences.strings; sourceTree = "<group>"; }; 8347435D20E6D58800063D45 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Preferences.strings; sourceTree = "<group>"; };
@ -313,6 +316,8 @@
83F27E731810E45D00CEF538 /* PathToFileTransformer.m */, 83F27E731810E45D00CEF538 /* PathToFileTransformer.m */,
83A3B72A283AE04800CC6593 /* ColorToValueTransformer.h */, 83A3B72A283AE04800CC6593 /* ColorToValueTransformer.h */,
83A3B72B283AE04800CC6593 /* ColorToValueTransformer.m */, 83A3B72B283AE04800CC6593 /* ColorToValueTransformer.m */,
833A899D286FF3850022E036 /* TimeIntervalToStringTransformer.h */,
833A899E286FF3850022E036 /* TimeIntervalToStringTransformer.m */,
); );
name = Transformers; name = Transformers;
sourceTree = "<group>"; sourceTree = "<group>";
@ -487,6 +492,7 @@
83A3B72C283AE04800CC6593 /* ColorToValueTransformer.m in Sources */, 83A3B72C283AE04800CC6593 /* ColorToValueTransformer.m in Sources */,
837C0D401C50954000CAE18F /* MIDIPluginBehaviorArrayController.m in Sources */, 837C0D401C50954000CAE18F /* MIDIPluginBehaviorArrayController.m in Sources */,
17C6433F0B8A783F00C53518 /* OutputPane.m in Sources */, 17C6433F0B8A783F00C53518 /* OutputPane.m in Sources */,
833A899F286FF3850022E036 /* TimeIntervalToStringTransformer.m in Sources */,
99F1813F0DE01D7A00FD5FFB /* PlaylistBehaviorArrayController.m in Sources */, 99F1813F0DE01D7A00FD5FFB /* PlaylistBehaviorArrayController.m in Sources */,
8372053718E3DEAF007EFAD4 /* ResamplerBehaviorArrayController.m in Sources */, 8372053718E3DEAF007EFAD4 /* ResamplerBehaviorArrayController.m in Sources */,
); );

View File

@ -0,0 +1,16 @@
//
// TimeIntervalToStringTransformer.h
// Preferences
//
// Created by Christopher Snowhill on 7/1/22.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface TimeIntervalToStringTransformer : NSValueTransformer
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,63 @@
//
// TimeIntervalToStringTransformer.m
// Preferences
//
// Created by Christopher Snowhill on 7/1/22.
//
#import "TimeIntervalToStringTransformer.h"
#import <math.h>
@implementation TimeIntervalToStringTransformer
+ (Class)transformedValueClass {
return [NSString class];
}
+ (BOOL)allowsReverseTransformation {
return YES;
}
// Convert from string to NSURL
- (id)reverseTransformedValue:(id)value {
if(value == nil) return nil;
if([value isKindOfClass:[NSString class]]) {
NSString *theString = (NSString *)value;
NSArray *components = [theString componentsSeparatedByString:@":"];
double interval = 0.0;
for(size_t i = 0, j = [components count]; i < j; ++i) {
interval += ([components[j - i - 1] doubleValue]) * pow(60.0, i);
}
return @(interval);
}
return nil;
}
- (id)transformedValue:(id)value {
if(value == nil) return @"";
if([value isKindOfClass:[NSNumber class]]) {
NSDateComponentsFormatter *formatter = [[NSDateComponentsFormatter alloc] init];
[formatter setAllowedUnits:NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond];
double secondsValue = [value doubleValue];
double fractionValue = fmod(secondsValue, 1.0);
secondsValue = (double)(int)secondsValue;
NSString *wholePart = [formatter stringFromTimeInterval:(NSTimeInterval)secondsValue];
NSUInteger fractionMillis = (int)(fractionValue * 1000.0);
if(fractionMillis >= 1) {
NSString *fractionPart = [NSString stringWithFormat:@".%03lu", fractionMillis];
fractionPart = [fractionPart stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithRange:NSMakeRange('0', 1)]];
return [wholePart stringByAppendingString:fractionPart];
}
return wholePart;
}
return @"";
}
@end

View File

@ -11,18 +11,6 @@
/* Class = "NSMenuItem"; title = "Item3"; ObjectID = "64"; */ /* Class = "NSMenuItem"; title = "Item3"; ObjectID = "64"; */
"64.title" = "Item3"; "64.title" = "Item3";
/* Class = "NSMenu"; title = "OtherViews"; ObjectID = "107"; */
"107.title" = "OtherViews";
/* Class = "NSMenuItem"; title = "Stable"; ObjectID = "108"; */
"108.title" = "Stable";
/* Class = "NSMenuItem"; title = "Unstable"; ObjectID = "109"; */
"109.title" = "Unstable";
/* Class = "NSMenuItem"; title = "Nightly"; ObjectID = "110"; */
"110.title" = "Nightly";
/* Class = "NSTextFieldCell"; title = "Play:"; ObjectID = "198"; */ /* Class = "NSTextFieldCell"; title = "Play:"; ObjectID = "198"; */
"198.title" = "Play:"; "198.title" = "Play:";
@ -35,9 +23,6 @@
/* Class = "NSButtonCell"; title = "Automatically check for updates on startup"; ObjectID = "207"; */ /* Class = "NSButtonCell"; title = "Automatically check for updates on startup"; ObjectID = "207"; */
"207.title" = "Automatically check for updates on startup"; "207.title" = "Automatically check for updates on startup";
/* Class = "NSTextFieldCell"; title = "Update Feed:"; ObjectID = "209"; */
"209.title" = "Update Feed:";
/* Class = "NSTextFieldCell"; title = "Output Device: "; ObjectID = "211"; */ /* Class = "NSTextFieldCell"; title = "Output Device: "; ObjectID = "211"; */
"211.title" = "Output Device: "; "211.title" = "Output Device: ";
@ -80,15 +65,9 @@
/* Class = "NSMenuItem"; title = "Item 2"; ObjectID = "1Yq-6f-Uho"; */ /* Class = "NSMenuItem"; title = "Item 2"; ObjectID = "1Yq-6f-Uho"; */
"1Yq-6f-Uho.title" = "Item 2"; "1Yq-6f-Uho.title" = "Item 2";
/* Class = "NSButtonCell"; title = "Enable Last.fm support (Last.fm client must be installed)"; ObjectID = "2N5-DH-IO6"; */
"2N5-DH-IO6.title" = "Enable Last.fm support (Last.fm client must be installed)";
/* Class = "NSMenuItem"; title = "Item 1"; ObjectID = "3Gx-cs-3B0"; */ /* Class = "NSMenuItem"; title = "Item 1"; ObjectID = "3Gx-cs-3B0"; */
"3Gx-cs-3B0.title" = "Item 1"; "3Gx-cs-3B0.title" = "Item 1";
/* Class = "NSButtonCell"; title = "Allow Last.fm client to control media keys"; ObjectID = "4Yi-67-ivc"; */
"4Yi-67-ivc.title" = "Allow Last.fm client to control media keys";
/* Class = "NSMenuItem"; title = "Item 2"; ObjectID = "99B-Tx-dPH"; */ /* Class = "NSMenuItem"; title = "Item 2"; ObjectID = "99B-Tx-dPH"; */
"99B-Tx-dPH.title" = "Item 2"; "99B-Tx-dPH.title" = "Item 2";
@ -164,5 +143,86 @@
/* Class = "NSButtonCell"; title = "Select a SoundFont"; ObjectID = "yeL-9c-lFq"; */ /* Class = "NSButtonCell"; title = "Select a SoundFont"; ObjectID = "yeL-9c-lFq"; */
"yeL-9c-lFq.title" = "Select a SoundFont"; "yeL-9c-lFq.title" = "Select a SoundFont";
/* Class = "NSButtonCell"; title = "Automatically launch Last.fm client"; ObjectID = "ze8-9p-SeX"; */ /* Class = "NSTextFieldCell"; title = "Hz"; ObjectID = "0Am-5Y-EKq"; */
"ze8-9p-SeX.title" = "Automatically launch Last.fm client"; "0Am-5Y-EKq.title" = "Hz";
/* Class = "NSButtonCell"; title = "Reset to defaults"; ObjectID = "1y7-iZ-BhE"; */
"1y7-iZ-BhE.title" = "Reset to defaults";
/* Class = "NSTextFieldCell"; title = "Table View Cell"; ObjectID = "7un-em-D8r"; */
"7un-em-D8r.title" = "Table View Cell";
/* Class = "NSTextFieldCell"; title = "Sample rate:"; ObjectID = "A9I-fr-vHp"; */
"A9I-fr-vHp.title" = "Sample rate:";
/* Class = "NSTextFieldCell"; title = "Default play time:"; ObjectID = "AQZ-ku-F8u"; */
"AQZ-ku-F8u.title" = "Default play time:";
/* Class = "NSTextFieldCell"; title = "Spectrum bars"; ObjectID = "Bll-IJ-lje"; */
"Bll-IJ-lje.title" = "Spectrum bars";
/* Class = "NSTextFieldCell"; title = "Spectrum peaks"; ObjectID = "CQI-YZ-B3V"; */
"CQI-YZ-B3V.title" = "Spectrum peaks";
/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "Dhd-k8-ZXq"; */
"Dhd-k8-ZXq.title" = "Text Cell";
/* Class = "NSTextFieldCell"; title = "Default loop count:"; ObjectID = "Fgm-Vs-tgU"; */
"Fgm-Vs-tgU.title" = "Default loop count:";
/* Class = "NSMenuItem"; title = "Delete Invalid Paths"; ObjectID = "JU5-o7-jid"; */
"JU5-o7-jid.title" = "Delete Invalid Paths";
/* Class = "NSMenuItem"; title = "Add Path"; ObjectID = "JxP-0t-mTB"; */
"JxP-0t-mTB.title" = "Add Path";
/* Class = "NSTextFieldCell"; title = "Table View Cell"; ObjectID = "LwT-Qb-47r"; */
"LwT-Qb-47r.title" = "Table View Cell";
/* Class = "NSTextFieldCell"; title = "(will be preferred if possible)"; ObjectID = "POG-ai-6D2"; */
"POG-ai-6D2.title" = "(will be preferred if possible)";
/* Class = "NSButtonCell"; title = "Quit when playback completes"; ObjectID = "SBA-J5-rEd"; */
"SBA-J5-rEd.title" = "Quit when playback completes";
/* Class = "NSTextFieldCell"; title = "Default fade time:"; ObjectID = "UdW-qd-A0x"; */
"UdW-qd-A0x.title" = "Default fade time:";
/* Class = "NSTableColumn"; headerCell.title = "Path"; ObjectID = "Yz2-Ee-bZ0"; */
"Yz2-Ee-bZ0.headerCell.title" = "Path";
/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "bWQ-dT-X3w"; */
"bWQ-dT-X3w.title" = "Text Cell";
/* Class = "NSButtonCell"; title = "Limit volume control to 100%"; ObjectID = "ds2-aw-ebU"; */
"ds2-aw-ebU.title" = "Limit volume control to 100%";
/* Class = "NSButtonCell"; title = "Spectrum 2D view"; ObjectID = "gXL-j6-df0"; */
"gXL-j6-df0.title" = "Spectrum 2D view";
/* Class = "NSTextFieldCell"; title = "hh:mm:ss.ms"; ObjectID = "klv-Wh-0ur"; */
"klv-Wh-0ur.title" = "hh:mm:ss.ms";
/* Class = "NSTextFieldCell"; title = "hh:mm:ss.ms"; ObjectID = "zaI-0m-tQf"; */
"zaI-0m-tQf.title" = "hh:mm:ss.ms";
/* Class = "NSTableColumn"; headerCell.title = "Valid"; ObjectID = "lEg-E3-TBs"; */
"lEg-E3-TBs.headerCell.title" = "Valid";
/* Class = "NSMenuItem"; title = "Delete Path"; ObjectID = "nva-pz-xSS"; */
"nva-pz-xSS.title" = "Delete Path";
/* Class = "NSMenuItem"; title = "Suggest Paths"; ObjectID = "qjI-dK-nfG"; */
"qjI-dK-nfG.title" = "Suggest Paths";
/* Class = "NSButtonCell"; title = "Allow insecure SSL connections"; ObjectID = "sva-DV-ina"; */
"sva-DV-ina.title" = "Allow insecure SSL connections";
/* Class = "NSButtonCell"; title = "Show stop button"; ObjectID = "vMI-lj-Lrz"; */
"vMI-lj-Lrz.title" = "Show stop button";
/* Class = "NSTextFieldCell"; title = "Folder access paths:"; ObjectID = "wWm-AD-cD4"; */
"wWm-AD-cD4.title" = "Folder access paths:";
/* Class = "NSButtonCell"; title = "Send crash reports and usage data"; ObjectID = "zQ2-6O-3Og"; */
"zQ2-6O-3Og.title" = "Send crash reports and usage data";

View File

@ -199,3 +199,44 @@
/* Class = "NSButtonCell"; title = "Send crash reports and usage data"; ObjectID = "zQ2-6O-3Og"; */ /* Class = "NSButtonCell"; title = "Send crash reports and usage data"; ObjectID = "zQ2-6O-3Og"; */
"zQ2-6O-3Og.title" = "Enviar informes de fallas y datos de uso"; "zQ2-6O-3Og.title" = "Enviar informes de fallas y datos de uso";
/* Class = "NSTextFieldCell"; title = "Default loop count:"; ObjectID = "Fgm-Vs-tgU"; */
"Fgm-Vs-tgU.title" = "Default loop count:";
/* Class = "NSTextFieldCell"; title = "Hz"; ObjectID = "0Am-5Y-EKq"; */
"0Am-5Y-EKq.title" = "Hz";
/* Class = "NSMenuItem"; title = "Item 3"; ObjectID = "1Cb-TU-E0q"; */
"1Cb-TU-E0q.title" = "Item 3";
/* Class = "NSMenuItem"; title = "Item 2"; ObjectID = "1Yq-6f-Uho"; */
"1Yq-6f-Uho.title" = "Item 2";
/* Class = "NSButtonCell"; title = "Reset to defaults"; ObjectID = "1y7-iZ-BhE"; */
"1y7-iZ-BhE.title" = "Reset to defaults";
/* Class = "NSMenuItem"; title = "Item 1"; ObjectID = "3Gx-cs-3B0"; */
"3Gx-cs-3B0.title" = "Item 1";
/* Class = "NSTextFieldCell"; title = "Table View Cell"; ObjectID = "7un-em-D8r"; */
"7un-em-D8r.title" = "Celda de vista de tabla";
/* Class = "NSMenuItem"; title = "Item 2"; ObjectID = "99B-Tx-dPH"; */
"99B-Tx-dPH.title" = "Item 2";
/* Class = "NSTextFieldCell"; title = "Sample rate:"; ObjectID = "A9I-fr-vHp"; */
"A9I-fr-vHp.title" = "Sample rate:";
/* Class = "NSTextFieldCell"; title = "Default play time:"; ObjectID = "AQZ-ku-F8u"; */
"AQZ-ku-F8u.title" = "Default play time:";
/* Class = "NSTextFieldCell"; title = "(will be preferred if possible)"; ObjectID = "POG-ai-6D2"; */
"POG-ai-6D2.title" = "(will be preferred if possible)";
/* Class = "NSTextFieldCell"; title = "Default fade time:"; ObjectID = "UdW-qd-A0x"; */
"UdW-qd-A0x.title" = "Default fade time:";
/* Class = "NSTextFieldCell"; title = "hh:mm:ss.ms"; ObjectID = "klv-Wh-0ur"; */
"klv-Wh-0ur.title" = "hh:mm:ss.ms";
/* Class = "NSTextFieldCell"; title = "hh:mm:ss.ms"; ObjectID = "zaI-0m-tQf"; */
"zaI-0m-tQf.title" = "hh:mm:ss.ms";