virtual alure::SharedPtr<alure::Decoder> createDecoder(alure::UniquePtr<std::istream> &file) { static const std::array<DUH*(*)(DUMBFILE*),3> init_funcs{{ dumb_read_it, dumb_read_xm, dumb_read_s3m }}; auto dfs = alure::MakeUnique<DUMBFILE_SYSTEM>(); dfs->open = nullptr; dfs->skip = cb_skip; dfs->getc = cb_read_char; dfs->getnc = cb_read; dfs->close = nullptr; dfs->seek = cb_seek; dfs->get_size = cb_get_size; DUMBFILE *dfile = dumbfile_open_ex(file.get(), dfs.get()); if(!dfile) return nullptr; ALuint freq = alure::Context::GetCurrent()->getDevice()->getFrequency(); DUH_SIGRENDERER *renderer; DUH *duh; for(auto init : init_funcs) { if((duh=init(dfile)) != nullptr) { if((renderer=duh_start_sigrenderer(duh, 0, 2, 0)) != nullptr) return alure::MakeShared<DumbDecoder>( std::move(file), std::move(dfs), dfile, duh, renderer, freq ); unload_duh(duh); duh = nullptr; } dumbfile_seek(dfile, 0, SEEK_SET); } if((duh=dumb_read_mod(dfile, 1)) != nullptr) { if((renderer=duh_start_sigrenderer(duh, 0, 2, 0)) != nullptr) return alure::MakeShared<DumbDecoder>( std::move(file), std::move(dfs), dfile, duh, renderer, freq ); unload_duh(duh); duh = nullptr; } dumbfile_close(dfile); return nullptr; }
/* load_duh(): loads a .duh file, returning a pointer to a DUH struct. * When you have finished with it, you must pass the pointer to unload_duh() * so that the memory can be freed. */ DUH *load_duh(const char *filename) { DUH *duh; DUMBFILE *f = dumbfile_open(filename); if (!f) return NULL; duh = read_duh(f); dumbfile_close(f); return duh; }
/* dumb_load_it_quick(): loads an IT file into a DUH struct, returning a * pointer to the DUH struct. When you have finished with it, you must pass * the pointer to unload_duh() so that the memory can be freed. */ DUH *dumb_load_it_quick(const char *filename) { DUH *duh; DUMBFILE *f = dumbfile_open(filename); if (!f) return NULL; duh = dumb_read_it_quick(f); dumbfile_close(f); return duh; }
/* dumb_load_psm_quick(): loads a PSM file into a DUH struct, returning a * pointer to the DUH struct. When you have finished with it, you must * pass the pointer to unload_duh() so that the memory can be freed. */ DUH *dumb_load_psm_quick(const char *filename, int subsong) { DUH *duh; DUMBFILE *f = dumbfile_open(filename); if (!f) return NULL; duh = dumb_read_psm_quick(f, subsong); dumbfile_close(f); return duh; }
/* dumb_load_mod_quick(): loads a MOD file into a DUH struct, returning a * pointer to the DUH struct. When you have finished with it, you must * pass the pointer to unload_duh() so that the memory can be freed. */ DUH *DUMBEXPORT dumb_load_mod_quick(const char *filename, int restrict) { DUH *duh; DUMBFILE *f = dumbfile_open(filename); if (!f) return NULL; duh = dumb_read_mod_quick(f, restrict); dumbfile_close(f); return duh; }
static void *dat_read_xm_quick(PACKFILE *f, long size) { DUMBFILE *df; DUH *duh; (void)size; df = dumbfile_open_packfile(f); if (!df) return NULL; duh = dumb_read_xm_quick(df); dumbfile_close(df); return duh; }
bool MODDecoder::Close(CFErrorRef */*error*/) { if(!IsOpen()) { log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger("org.sbooth.AudioEngine.AudioDecoder.MOD"); LOG4CXX_WARN(logger, "Close() called on an AudioDecoder that hasn't been opened"); return true; } if(dsr) duh_end_sigrenderer(dsr), dsr = NULL; if(duh) unload_duh(duh), duh = NULL; if(df) dumbfile_close(df), df = NULL; mIsOpen = false; return true; }
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; }