[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: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
[[NSUserDefaults standardUserDefaults] registerDefaults:userDefaultsValuesDict];
[[NSUserDefaults standardUserDefaults] synchronize];

View File

@ -7,6 +7,7 @@
objects = {
/* 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 */; };
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, ); }; };
@ -51,6 +52,7 @@
/* End PBXCopyFilesBuildPhase 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>"; };
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>"; };
@ -77,6 +79,7 @@
files = (
83D3C6A6201D3951005564CB /* libbinio.framework in Frameworks */,
833AFD3620E4ED9D00F0C21E /* libAdPlug.framework in Frameworks */,
833A899A286FF2FD0022E036 /* Cocoa.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -141,6 +144,7 @@
83D3C602201C675D005564CB /* Frameworks */ = {
isa = PBXGroup;
children = (
833A8999286FF2FD0022E036 /* Cocoa.framework */,
83D3C6A7201D3951005564CB /* libbinio.framework */,
83D3C603201C6775005564CB /* libAdPlug.xcodeproj */,
);

View File

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

View File

@ -47,7 +47,14 @@ static CAdPlugDatabase *g_database = NULL;
- (BOOL)open:(id<CogSource>)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];
NSRange fragmentRange = [path rangeOfString:@"#" options:NSBackwardsSearch];
@ -68,7 +75,7 @@ static CAdPlugDatabase *g_database = NULL;
samples_todo = 0;
length = m_player->songlength(subsong) * 441 / 10;
length = m_player->songlength(subsong) * sampleRate / 1000.0;
current_pos = 0;
m_player->rewind(subsong);
@ -81,7 +88,7 @@ static CAdPlugDatabase *g_database = NULL;
- (NSDictionary *)properties {
return @{ @"bitrate": @(0),
@"sampleRate": @(44100.0),
@"sampleRate": @(sampleRate),
@"totalFrames": @(length),
@"bitsPerSample": @(16), // Samples are short
@"floatingPoint": @(NO),
@ -106,7 +113,7 @@ static CAdPlugDatabase *g_database = NULL;
if(!samples_todo) {
running = m_player->update() && running;
if(!dont_loop || running) {
samples_todo = 44100 / m_player->getrefresh();
samples_todo = (int)ceil(sampleRate / m_player->getrefresh());
current_pos += samples_todo;
}
}
@ -132,7 +139,7 @@ static CAdPlugDatabase *g_database = NULL;
while(current_pos < frame) {
m_player->update();
current_pos += 44100 / m_player->getrefresh();
current_pos += (long)ceil(sampleRate / m_player->getrefresh());
}
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> {
Music_Emu* emu;
id<CogSource> source;
long sampleRate;
double sampleRate;
long length;
long fade;
NSString* codec;

View File

@ -53,10 +53,15 @@ gme_err_t readCallback(void *data, void *out, int count) {
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)
sampleRate = 32000;
sampleRate = 32000.0;
emu = gme_new_emu(type, (int)sampleRate);
if(!emu) {
@ -109,16 +114,30 @@ gme_err_t readCallback(void *data, void *out, int count) {
length = info->length;
} else if(info->loop_length > 0) {
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 {
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);
}
if(info->fade_length >= 0) {
fade = info->fade_length;
} 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);
@ -143,7 +162,7 @@ gme_err_t readCallback(void *data, void *out, int count) {
- (NSDictionary *)properties {
return @{ @"bitrate": @(0),
@"sampleRate": @(sampleRate),
@"totalFrames": @((long)(length * ((float)sampleRate * 0.001))),
@"totalFrames": @((long)(length * (sampleRate * 0.001))),
@"bitsPerSample": @(sizeof(short) * 8), // Samples are short
@"channels": @(2), // output from gme_play is in stereo
@"seekable": @(YES),
@ -176,7 +195,7 @@ gme_err_t readCallback(void *data, void *out, int count) {
- (long)seek:(long)frame {
gme_err_t error;
error = gme_seek(emu, frame / 44.1);
error = gme_seek(emu, frame * sampleRate * 0.001);
if(error) {
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;
if(!tagLengthMs) {
tagLengthMs = (2 * 60 + 30) * 1000;
tagFadeMs = 8000;
double defaultLength = [[[[NSUserDefaultsController sharedUserDefaultsController] defaults] valueForKey:@"synthDefaultSeconds"] doubleValue];
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;

View File

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

View File

@ -33,10 +33,17 @@ static void oneTimeInit(void) {
if(size > UINT_MAX)
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);
[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);
if(!tune)
return NO;
@ -62,14 +69,19 @@ static void oneTimeInit(void) {
++loops;
}
framesLength = tune->ht_PlayingTime * 44100 / (tune->ht_SpeedMultiplier * 50);
framesFade = 44100 * 8;
double defaultFade = [[[[NSUserDefaultsController sharedUserDefaultsController] defaults] valueForKey:@"synthDefaultFadeSeconds"] doubleValue];
if(defaultFade < 0.0) {
defaultFade = 0.0;
}
framesLength = tune->ht_PlayingTime * sampleRate / (tune->ht_SpeedMultiplier * 50);
framesFade = (int)ceil(sampleRate * defaultFade);
totalFrames = framesLength + framesFade;
framesRead = 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);
@ -81,7 +93,7 @@ static void oneTimeInit(void) {
- (NSDictionary *)properties {
return @{ @"bitrate": @(0),
@"sampleRate": @(44100),
@"sampleRate": @(sampleRate),
@"totalFrames": @(totalFrames),
@"bitsPerSample": @(32),
@"floatingPoint": @(YES),
@ -121,7 +133,7 @@ static void oneTimeInit(void) {
}
}
hvl_DecodeFrame(tune, (int8_t *)buffer, ((int8_t *)buffer) + 4, 8);
framesInBuffer = 44100 / 50;
framesInBuffer = (int)ceil(sampleRate / 50);
}
if(!repeatone && framesRead + total > framesLength) {
@ -156,7 +168,7 @@ static void oneTimeInit(void) {
while(framesRead < frame) {
hvl_play_irq(tune);
framesRead += 44100 / 50;
framesRead += (int)ceil(sampleRate / 50);
}
return framesRead;

View File

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

View File

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

View File

@ -7,6 +7,7 @@
objects = {
/* 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 */; };
83E5FE731FFF010C00659F0F /* OMPTDecoder.mm in Sources */ = {isa = PBXBuildFile; fileRef = 83E5FE6D1FFF010B00659F0F /* OMPTDecoder.mm */; };
83E5FE741FFF010C00659F0F /* OMPTContainer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 83E5FE6F1FFF010B00659F0F /* OMPTContainer.mm */; };
@ -47,6 +48,7 @@
/* End PBXCopyFilesBuildPhase 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>"; };
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>"; };
@ -67,6 +69,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
833A899C286FF3150022E036 /* Cocoa.framework in Frameworks */,
83F30AE8286EBD2A0005EF06 /* libOpenMPT.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -113,6 +116,7 @@
83E5EFB21FFEF79000659F0F /* Frameworks */ = {
isa = PBXGroup;
children = (
833A899B286FF3150022E036 /* Cocoa.framework */,
83F30A81286EBB420005EF06 /* libOpenMPT.xcodeproj */,
);
name = Frameworks;

View File

@ -19,6 +19,8 @@
id<CogSource> source;
long length;
double sampleRate;
}
- (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];
[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));
[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);
length = mod->get_duration_seconds() * 44100.0;
length = mod->get_duration_seconds() * sampleRate;
mod->set_repeat_count(IsRepeatOneSet() ? -1 : 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 {
return @{ @"bitrate": @(0),
@"sampleRate": @(44100),
@"sampleRate": @(sampleRate),
@"totalFrames": @(length),
@"bitsPerSample": @(32),
@"floatingPoint": @(YES),
@ -114,7 +121,7 @@ static void g_push_archive_extensions(std::vector<std::string> &list) {
if(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)
break;
@ -128,7 +135,7 @@ static void g_push_archive_extensions(std::vector<std::string> &list) {
}
- (long)seek:(long)frame {
mod->set_position_seconds(frame * (1.0 / 44100.0));
mod->set_position_seconds(frame / sampleRate);
return frame;
}

View File

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

View File

@ -88,7 +88,6 @@ static void PlayerLogCallback(void* userParam, PlayerBase* player, UINT8 level,
return;
}
const int sampleRate = 44100;
const int numChannels = 2;
const int numBitsPerSample = 24;
const int smplAlloc = 2048;
@ -112,8 +111,24 @@ const int masterVol = 0x10000; // Fixed point 16.16
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();
uint32_t maxLoops = repeatOne ? 0 : 2;
uint32_t maxLoops = repeatOne ? 0 : (uint32_t)loopCount;
mainPlr = new PlayerA;
mainPlr->RegisterPlayerEngine(new VGMPlayer);
@ -127,12 +142,12 @@ const int masterVol = 0x10000; // Fixed point 16.16
PlayerA::Config pCfg = mainPlr->GetConfiguration();
pCfg.masterVol = masterVol;
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.pbSpeed = 1.0;
mainPlr->SetConfiguration(pCfg);
}
mainPlr->SetOutputSettings(sampleRate, numChannels, numBitsPerSample, smplAlloc);
mainPlr->SetOutputSettings((int)ceil(sampleRate), numChannels, numBitsPerSample, smplAlloc);
[source seek:0 whence:SEEK_END];
size_t size = [source tell];
@ -198,7 +213,7 @@ const int masterVol = 0x10000; // Fixed point 16.16
return 0;
BOOL repeatOne = IsRepeatOneSet();
uint32_t maxLoops = repeatOne ? 0 : 2;
uint32_t maxLoops = repeatOne ? 0 : (uint32_t)loopCount;
PlayerBase* player = mainPlr->GetPlayer();
mainPlr->SetLoopCount(maxLoops);

View File

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

View File

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

View File

@ -10,6 +10,7 @@
8314D8091A35654900EEE8E6 /* SidDecoder.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8314D8041A35654900EEE8E6 /* SidDecoder.mm */; };
8314D80A1A35654900EEE8E6 /* SidMetadataReader.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8314D8061A35654900EEE8E6 /* SidMetadataReader.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 */; };
83747C012862DA420021245F /* Shared.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 83747BFF2862DA420021245F /* Shared.xcconfig */; };
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>"; };
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>"; };
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; };
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>"; };
@ -62,6 +64,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
833A8998286FF2E30022E036 /* Cocoa.framework in Frameworks */,
EDBE911825E7EA01001EB4A4 /* sidplayfp.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -117,6 +120,7 @@
8314D64A1A354E4400EEE8E6 /* Frameworks */ = {
isa = PBXGroup;
children = (
833A8996286FF2E30022E036 /* Cocoa.framework */,
EDBE8F0A25E7E74D001EB4A4 /* sidplayfp.xcodeproj */,
);
name = Frameworks;

View File

@ -30,6 +30,8 @@
BOOL playForever;
BOOL canPlayForever;
int loopCount;
double fadeTime;
int sampleRate;
int channels;
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 {
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];
NSRange fragmentRange = [path rangeOfString:@"#" options:NSBackwardsSearch];
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.play_forever = playForever;
vcfg.loop_count = 2;
vcfg.fade_time = 10;
vcfg.loop_count = loopCount;
vcfg.fade_time = fadeTime;
vcfg.fade_delay = 0;
vcfg.ignore_loop = 0;

View File

@ -611,11 +611,11 @@
<point key="canvasLocation" x="450" y="183"/>
</customView>
<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"/>
<subviews>
<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"/>
<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"/>
@ -626,7 +626,7 @@
</connections>
</button>
<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"/>
<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"/>
@ -635,7 +635,7 @@
</textFieldCell>
</textField>
<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"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Label" id="ECB-P0-pve">
<font key="font" metaFont="system"/>
@ -652,7 +652,7 @@
</textFieldCell>
</textField>
<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"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Resampling Quality:" id="eX0-PC-iVo">
<font key="font" metaFont="system"/>
@ -661,7 +661,7 @@
</textFieldCell>
</textField>
<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"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="MIDI Plugin:" id="n5F-dq-NZh">
<font key="font" metaFont="system"/>
@ -670,7 +670,7 @@
</textFieldCell>
</textField>
<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"/>
<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"/>
@ -691,7 +691,7 @@
</connections>
</popUpButton>
<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"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="MIDI Flavor:" id="FQF-vJ-hBx">
<font key="font" metaFont="system"/>
@ -700,7 +700,7 @@
</textFieldCell>
</textField>
<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"/>
<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"/>
@ -721,7 +721,7 @@
</connections>
</popUpButton>
<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"/>
<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"/>
@ -741,8 +741,138 @@
<binding destination="52" name="selectedObject" keyPath="values.resampling" previousBinding="KxI-52-0UK" id="wsy-tb-NFy"/>
</connections>
</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>
<point key="canvasLocation" x="450" y="339"/>
<point key="canvasLocation" x="450" y="391"/>
</customView>
<arrayController objectClassName="NSDictionary" editable="NO" id="JB6-r9-XpG" userLabel="ResamplerBehavior" customClass="ResamplerBehaviorArrayController">
<declaredKeys>

View File

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

View File

@ -22,6 +22,7 @@
8307D31728606EAF000FF8EB /* growl@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 8307D31328606EAF000FF8EB /* growl@2x.png */; };
8307D31828606EAF000FF8EB /* general.png in Resources */ = {isa = PBXBuildFile; fileRef = 8307D31428606EAF000FF8EB /* general.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 */; };
8372053718E3DEAF007EFAD4 /* ResamplerBehaviorArrayController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8372053618E3DEAF007EFAD4 /* ResamplerBehaviorArrayController.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>"; };
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>"; };
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>"; };
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>"; };
@ -313,6 +316,8 @@
83F27E731810E45D00CEF538 /* PathToFileTransformer.m */,
83A3B72A283AE04800CC6593 /* ColorToValueTransformer.h */,
83A3B72B283AE04800CC6593 /* ColorToValueTransformer.m */,
833A899D286FF3850022E036 /* TimeIntervalToStringTransformer.h */,
833A899E286FF3850022E036 /* TimeIntervalToStringTransformer.m */,
);
name = Transformers;
sourceTree = "<group>";
@ -487,6 +492,7 @@
83A3B72C283AE04800CC6593 /* ColorToValueTransformer.m in Sources */,
837C0D401C50954000CAE18F /* MIDIPluginBehaviorArrayController.m in Sources */,
17C6433F0B8A783F00C53518 /* OutputPane.m in Sources */,
833A899F286FF3850022E036 /* TimeIntervalToStringTransformer.m in Sources */,
99F1813F0DE01D7A00FD5FFB /* PlaylistBehaviorArrayController.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"; */
"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"; */
"198.title" = "Play:";
@ -35,9 +23,6 @@
/* Class = "NSButtonCell"; title = "Automatically check for updates on startup"; ObjectID = "207"; */
"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"; */
"211.title" = "Output Device: ";
@ -80,15 +65,9 @@
/* Class = "NSMenuItem"; title = "Item 2"; ObjectID = "1Yq-6f-Uho"; */
"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"; */
"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"; */
"99B-Tx-dPH.title" = "Item 2";
@ -164,5 +143,86 @@
/* Class = "NSButtonCell"; title = "Select a SoundFont"; ObjectID = "yeL-9c-lFq"; */
"yeL-9c-lFq.title" = "Select a SoundFont";
/* Class = "NSButtonCell"; title = "Automatically launch Last.fm client"; ObjectID = "ze8-9p-SeX"; */
"ze8-9p-SeX.title" = "Automatically launch Last.fm client";
/* Class = "NSTextFieldCell"; title = "Hz"; ObjectID = "0Am-5Y-EKq"; */
"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"; */
"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";