static void *dat_read_s3m(PACKFILE *f, long size) { DUMBFILE *df; DUH *duh; (void)size; df = dumbfile_open_packfile(f); if (!df) return NULL; duh = dumb_read_s3m(df); dumbfile_close(df); return duh; }
void* Init(const char* strFile, unsigned int filecache, int* channels, int* samplerate, int* bitspersample, int64_t* totaltime, int* bitrate, AEDataFormat* format, const AEChannel** channelinfo) { void* file = XBMC->OpenFile(strFile,0); if (!file) return NULL; dumbfile_mem_status memdata; memdata.size = XBMC->GetFileLength(file); memdata.ptr = new uint8_t[memdata.size]; XBMC->ReadFile(file, const_cast<uint8_t*>(memdata.ptr), memdata.size); XBMC->CloseFile(file); DUMBFILE* f = dumbfile_open_ex(&memdata, &mem_dfs); if (!f) return NULL; DumbContext* result = new DumbContext; if (memdata.size >= 4 && memdata.ptr[0] == 'I' && memdata.ptr[1] == 'M' && memdata.ptr[2] == 'P' && memdata.ptr[3] == 'M') { result->module = dumb_read_it(f); } else if (memdata.size >= 17 && memcmp(memdata.ptr, "Extended Module: ", 17) == 0) { result->module = dumb_read_xm(f); } else if (memdata.size >= 0x30 && memdata.ptr[0x2C] == 'S' && memdata.ptr[0x2D] == 'C' && memdata.ptr[0x2E] == 'R' && memdata.ptr[0x2F] == 'M') { result->module = dumb_read_s3m(f); } else { dumbfile_close(f); delete result; return NULL; } dumbfile_close(f); result->sr = duh_start_sigrenderer(result->module, 0, 2, 0); if (!result->sr) { delete result; return NULL; } *channels = 2; *samplerate = 48000; *bitspersample = 16; *totaltime = duh_get_length(result->module)/65536*1000; *format = AE_FMT_S16NE; static enum AEChannel map[3] = { AE_CH_FL, AE_CH_FR , AE_CH_NULL}; *channelinfo = map; *bitrate = duh_sigrenderer_get_n_channels(result->sr); return result; }
bool MODDecoder::Open(CFErrorRef *error) { if(IsOpen()) { log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger("org.sbooth.AudioEngine.AudioDecoder.MOD"); LOG4CXX_WARN(logger, "Open() called on an AudioDecoder that is already open"); return true; } // Ensure the input source is open if(!mInputSource->IsOpen() && !mInputSource->Open(error)) return false; dfs.open = NULL; dfs.skip = skip_callback; dfs.getc = getc_callback; dfs.getnc = getnc_callback; dfs.close = close_callback; df = dumbfile_open_ex(this, &dfs); if(NULL == df) { return false; } CFStringRef fileSystemPath = CFURLCopyFileSystemPath(GetURL(), kCFURLPOSIXPathStyle); CFStringRef extension = NULL; CFRange range; if(CFStringFindWithOptionsAndLocale(fileSystemPath, CFSTR("."), CFRangeMake(0, CFStringGetLength(fileSystemPath)), kCFCompareBackwards, CFLocaleGetSystem(), &range)) { extension = CFStringCreateWithSubstring(kCFAllocatorDefault, fileSystemPath, CFRangeMake(range.location + 1, CFStringGetLength(fileSystemPath) - range.location - 1)); } CFRelease(fileSystemPath), fileSystemPath = NULL; if(NULL == extension) { return false; } // Attempt to create the appropriate decoder based on the file's extension if(kCFCompareEqualTo == CFStringCompare(extension, CFSTR("it"), kCFCompareCaseInsensitive)) duh = dumb_read_it(df); else if(kCFCompareEqualTo == CFStringCompare(extension, CFSTR("xm"), kCFCompareCaseInsensitive)) duh = dumb_read_xm(df); else if(kCFCompareEqualTo == CFStringCompare(extension, CFSTR("s3m"), kCFCompareCaseInsensitive)) duh = dumb_read_s3m(df); else if(kCFCompareEqualTo == CFStringCompare(extension, CFSTR("mod"), kCFCompareCaseInsensitive)) duh = dumb_read_mod(df); CFRelease(extension), extension = NULL; if(NULL == duh) { if(error) { CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 32, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFStringRef displayName = CreateDisplayNameForURL(mInputSource->GetURL()); CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFCopyLocalizedString(CFSTR("The file “%@” is not a valid MOD file."), ""), displayName); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedDescriptionKey, errorString); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedFailureReasonKey, CFCopyLocalizedString(CFSTR("Not a MOD file"), "")); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedRecoverySuggestionKey, CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), "")); CFRelease(errorString), errorString = NULL; CFRelease(displayName), displayName = NULL; *error = CFErrorCreate(kCFAllocatorDefault, AudioDecoderErrorDomain, AudioDecoderInputOutputError, errorDictionary); CFRelease(errorDictionary), errorDictionary = NULL; } if(df) dumbfile_close(df), df = NULL; return false; } mTotalFrames = duh_get_length(duh); dsr = duh_start_sigrenderer(duh, 0, 2, 0); if(NULL == dsr) { if(error) { CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 32, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFStringRef displayName = CreateDisplayNameForURL(mInputSource->GetURL()); CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFCopyLocalizedString(CFSTR("The file “%@” is not a valid MOD file."), ""), displayName); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedDescriptionKey, errorString); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedFailureReasonKey, CFCopyLocalizedString(CFSTR("Not a MOD file"), "")); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedRecoverySuggestionKey, CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), "")); CFRelease(errorString), errorString = NULL; CFRelease(displayName), displayName = NULL; *error = CFErrorCreate(kCFAllocatorDefault, AudioDecoderErrorDomain, AudioDecoderInputOutputError, errorDictionary); CFRelease(errorDictionary), errorDictionary = NULL; } if(df) dumbfile_close(df), df = NULL; if(duh) unload_duh(duh), duh = NULL; return false; } // Generate interleaved 2 channel 44.1 16-bit output mFormat.mFormatID = kAudioFormatLinearPCM; mFormat.mFormatFlags = kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; mFormat.mSampleRate = DUMB_SAMPLE_RATE; mFormat.mChannelsPerFrame = DUMB_CHANNELS; mFormat.mBitsPerChannel = DUMB_BIT_DEPTH; mFormat.mBytesPerPacket = (mFormat.mBitsPerChannel / 8) * mFormat.mChannelsPerFrame; mFormat.mFramesPerPacket = 1; mFormat.mBytesPerFrame = mFormat.mBytesPerPacket * mFormat.mFramesPerPacket; mFormat.mReserved = 0; // Set up the source format mSourceFormat.mFormatID = 'MOD '; mSourceFormat.mSampleRate = DUMB_SAMPLE_RATE; mSourceFormat.mChannelsPerFrame = DUMB_CHANNELS; // Setup the channel layout mChannelLayout = CreateChannelLayoutWithTag(kAudioChannelLayoutTag_Stereo); mIsOpen = true; return true; }
bool SFB::Audio::MODDecoder::_Open(CFErrorRef *error) { dfs.open = nullptr; dfs.skip = skip_callback; dfs.getc = getc_callback; dfs.getnc = getnc_callback; dfs.close = close_callback; df = unique_DUMBFILE_ptr(dumbfile_open_ex(this, &dfs), dumbfile_close); if(!df) { return false; } SFB::CFString pathExtension = CFURLCopyPathExtension(GetURL()); if(nullptr == pathExtension) return false; // Attempt to create the appropriate decoder based on the file's extension if(kCFCompareEqualTo == CFStringCompare(pathExtension, CFSTR("it"), kCFCompareCaseInsensitive)) duh = unique_DUH_ptr(dumb_read_it(df.get()), unload_duh); else if(kCFCompareEqualTo == CFStringCompare(pathExtension, CFSTR("xm"), kCFCompareCaseInsensitive)) duh = unique_DUH_ptr(dumb_read_xm(df.get()), unload_duh); else if(kCFCompareEqualTo == CFStringCompare(pathExtension, CFSTR("s3m"), kCFCompareCaseInsensitive)) duh = unique_DUH_ptr(dumb_read_s3m(df.get()), unload_duh); else if(kCFCompareEqualTo == CFStringCompare(pathExtension, CFSTR("mod"), kCFCompareCaseInsensitive)) duh = unique_DUH_ptr(dumb_read_mod(df.get()), unload_duh); if(!duh) { if(error) { SFB::CFString description = CFCopyLocalizedString(CFSTR("The file “%@” is not a valid MOD file."), ""); SFB::CFString failureReason = CFCopyLocalizedString(CFSTR("Not a MOD file"), ""); SFB::CFString recoverySuggestion = CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""); *error = CreateErrorForURL(Decoder::ErrorDomain, Decoder::InputOutputError, description, mInputSource->GetURL(), failureReason, recoverySuggestion); } return false; } // NB: This must change if the sample rate changes because it is based on 65536 Hz mTotalFrames = duh_get_length(duh.get()); dsr = unique_DUH_SIGRENDERER_ptr(duh_start_sigrenderer(duh.get(), 0, 2, 0), duh_end_sigrenderer); if(!dsr) { if(error) { SFB::CFString description = CFCopyLocalizedString(CFSTR("The file “%@” is not a valid MOD file."), ""); SFB::CFString failureReason = CFCopyLocalizedString(CFSTR("Not a MOD file"), ""); SFB::CFString recoverySuggestion = CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""); *error = CreateErrorForURL(Decoder::ErrorDomain, Decoder::InputOutputError, description, mInputSource->GetURL(), failureReason, recoverySuggestion); } return false; } // Generate interleaved 2 channel 44.1 16-bit output mFormat.mFormatID = kAudioFormatLinearPCM; mFormat.mFormatFlags = kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; mFormat.mSampleRate = DUMB_SAMPLE_RATE; mFormat.mChannelsPerFrame = DUMB_CHANNELS; mFormat.mBitsPerChannel = DUMB_BIT_DEPTH; mFormat.mBytesPerPacket = (mFormat.mBitsPerChannel / 8) * mFormat.mChannelsPerFrame; mFormat.mFramesPerPacket = 1; mFormat.mBytesPerFrame = mFormat.mBytesPerPacket * mFormat.mFramesPerPacket; mFormat.mReserved = 0; // Set up the source format mSourceFormat.mFormatID = 'MOD '; mSourceFormat.mSampleRate = DUMB_SAMPLE_RATE; mSourceFormat.mChannelsPerFrame = DUMB_CHANNELS; // Setup the channel layout mChannelLayout = ChannelLayout::ChannelLayoutWithTag(kAudioChannelLayoutTag_Stereo); return true; }