3 |
* LinuxSampler - modular, streaming capable sampler * |
* LinuxSampler - modular, streaming capable sampler * |
4 |
* * |
* * |
5 |
* Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck * |
* Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck * |
6 |
* Copyright (C) 2005 - 2009 Christian Schoenebeck * |
* Copyright (C) 2005 - 2011 Christian Schoenebeck * |
7 |
* * |
* * |
8 |
* This program is free software; you can redistribute it and/or modify * |
* This program is free software; you can redistribute it and/or modify * |
9 |
* it under the terms of the GNU General Public License as published by * |
* it under the terms of the GNU General Public License as published by * |
30 |
#include "../../common/global_private.h" |
#include "../../common/global_private.h" |
31 |
#include "../../plugins/InstrumentEditorFactory.h" |
#include "../../plugins/InstrumentEditorFactory.h" |
32 |
|
|
|
// We need to know the maximum number of sample points which are going to |
|
|
// be processed for each render cycle of the audio output driver, to know |
|
|
// how much initial sample points we need to cache into RAM. If the given |
|
|
// sampler channel does not have an audio output device assigned yet |
|
|
// though, we simply use this default value. |
|
|
#define GIG_RESOURCE_MANAGER_DEFAULT_MAX_SAMPLES_PER_CYCLE 128 |
|
|
|
|
33 |
namespace LinuxSampler { namespace gig { |
namespace LinuxSampler { namespace gig { |
34 |
|
|
35 |
// data stored as long as an instrument resource exists |
// data stored as long as an instrument resource exists |
552 |
|
|
553 |
::gig::Instrument* InstrumentResourceManager::Create(instrument_id_t Key, InstrumentConsumer* pConsumer, void*& pArg) { |
::gig::Instrument* InstrumentResourceManager::Create(instrument_id_t Key, InstrumentConsumer* pConsumer, void*& pArg) { |
554 |
// get gig file from internal gig file manager |
// get gig file from internal gig file manager |
555 |
::gig::File* pGig = Gigs.Borrow(Key.FileName, (GigConsumer*) Key.Index); // conversion kinda hackish :/ |
::gig::File* pGig = Gigs.Borrow(Key.FileName, reinterpret_cast<GigConsumer*>(Key.Index)); // conversion kinda hackish :/ |
556 |
|
|
557 |
// we pass this to the progress callback mechanism of libgig |
// we pass this to the progress callback mechanism of libgig |
558 |
progress_callback_arg_t callbackArg; |
progress_callback_arg_t callbackArg; |
602 |
pEntry->ID.Index = Key.Index; |
pEntry->ID.Index = Key.Index; |
603 |
pEntry->pGig = pGig; |
pEntry->pGig = pGig; |
604 |
|
|
605 |
|
// (try to resolve the audio device context) |
606 |
EngineChannel* pEngineChannel = dynamic_cast<EngineChannel*>(pConsumer); |
EngineChannel* pEngineChannel = dynamic_cast<EngineChannel*>(pConsumer); |
607 |
|
Engine* pEngine = dynamic_cast<Engine*>(pEngineChannel->GetEngine()); |
608 |
|
AudioOutputDevice* pDevice = (pEngine) ? pEngine->pAudioOutputDevice : NULL; |
609 |
// and we save this to check if we need to reallocate for a engine with higher value of 'MaxSamplesPerSecond' |
// and we save this to check if we need to reallocate for a engine with higher value of 'MaxSamplesPerSecond' |
610 |
pEntry->MaxSamplesPerCycle = |
pEntry->MaxSamplesPerCycle = |
611 |
(!pEngineChannel) ? 0 /* don't care for instrument editors */ : |
(pDevice) ? pDevice->MaxSamplesPerCycle() : DefaultMaxSamplesPerCycle(); |
612 |
(pEngineChannel->GetEngine()) ? |
|
|
dynamic_cast<Engine*>(pEngineChannel->GetEngine())->pAudioOutputDevice->MaxSamplesPerCycle() |
|
|
: GIG_RESOURCE_MANAGER_DEFAULT_MAX_SAMPLES_PER_CYCLE; |
|
613 |
pArg = pEntry; |
pArg = pEntry; |
614 |
|
|
615 |
return pInstrument; |
return pInstrument; |
618 |
void InstrumentResourceManager::Destroy( ::gig::Instrument* pResource, void* pArg) { |
void InstrumentResourceManager::Destroy( ::gig::Instrument* pResource, void* pArg) { |
619 |
instr_entry_t* pEntry = (instr_entry_t*) pArg; |
instr_entry_t* pEntry = (instr_entry_t*) pArg; |
620 |
// we don't need the .gig file here anymore |
// we don't need the .gig file here anymore |
621 |
Gigs.HandBack(pEntry->pGig, (GigConsumer*) pEntry->ID.Index); // conversion kinda hackish :/ |
Gigs.HandBack(pEntry->pGig, reinterpret_cast<GigConsumer*>(pEntry->ID.Index)); // conversion kinda hackish :/ |
622 |
delete pEntry; |
delete pEntry; |
623 |
} |
} |
624 |
|
|
625 |
void InstrumentResourceManager::OnBorrow(::gig::Instrument* pResource, InstrumentConsumer* pConsumer, void*& pArg) { |
void InstrumentResourceManager::OnBorrow(::gig::Instrument* pResource, InstrumentConsumer* pConsumer, void*& pArg) { |
626 |
instr_entry_t* pEntry = (instr_entry_t*) pArg; |
instr_entry_t* pEntry = (instr_entry_t*) pArg; |
627 |
|
|
628 |
|
// (try to resolve the audio device context) |
629 |
EngineChannel* pEngineChannel = dynamic_cast<EngineChannel*>(pConsumer); |
EngineChannel* pEngineChannel = dynamic_cast<EngineChannel*>(pConsumer); |
630 |
|
Engine* pEngine = pEngineChannel ? dynamic_cast<Engine*>(pEngineChannel->GetEngine()) : NULL; |
631 |
|
AudioOutputDevice* pDevice = (pEngine) ? pEngine->pAudioOutputDevice : NULL; |
632 |
|
|
633 |
uint maxSamplesPerCycle = |
uint maxSamplesPerCycle = |
634 |
(pEngineChannel && pEngineChannel->GetEngine()) ? dynamic_cast<Engine*>(pEngineChannel->GetEngine())->pAudioOutputDevice->MaxSamplesPerCycle() |
(pDevice) ? pDevice->MaxSamplesPerCycle() : DefaultMaxSamplesPerCycle(); |
635 |
: GIG_RESOURCE_MANAGER_DEFAULT_MAX_SAMPLES_PER_CYCLE; |
|
636 |
if (pEntry->MaxSamplesPerCycle < maxSamplesPerCycle) { |
if (pEntry->MaxSamplesPerCycle < maxSamplesPerCycle) { |
637 |
|
dmsg(1,("Completely reloading instrument due to insufficient precached samples ...\n")); |
638 |
Update(pResource, pConsumer); |
Update(pResource, pConsumer); |
639 |
} |
} |
640 |
} |
} |
642 |
void InstrumentResourceManager::DeleteRegionIfNotUsed(::gig::DimensionRegion* pRegion, region_info_t* pRegInfo) { |
void InstrumentResourceManager::DeleteRegionIfNotUsed(::gig::DimensionRegion* pRegion, region_info_t* pRegInfo) { |
643 |
// TODO: we could delete Region and Instrument here if they have become unused |
// TODO: we could delete Region and Instrument here if they have become unused |
644 |
} |
} |
645 |
|
|
646 |
void InstrumentResourceManager::DeleteSampleIfNotUsed(::gig::Sample* pSample, region_info_t* pRegInfo) { |
void InstrumentResourceManager::DeleteSampleIfNotUsed(::gig::Sample* pSample, region_info_t* pRegInfo) { |
647 |
::gig::File* gig = pRegInfo->file; |
::gig::File* gig = pRegInfo->file; |
648 |
::RIFF::File* riff = static_cast< ::RIFF::File*>(pRegInfo->pArg); |
::RIFF::File* riff = static_cast< ::RIFF::File*>(pRegInfo->pArg); |
697 |
// the sample. |
// the sample. |
698 |
const uint maxSamplesPerCycle = |
const uint maxSamplesPerCycle = |
699 |
(pEngine) ? pEngine->pAudioOutputDevice->MaxSamplesPerCycle() |
(pEngine) ? pEngine->pAudioOutputDevice->MaxSamplesPerCycle() |
700 |
: GIG_RESOURCE_MANAGER_DEFAULT_MAX_SAMPLES_PER_CYCLE; |
: DefaultMaxSamplesPerCycle(); |
701 |
const uint neededSilenceSamples = (maxSamplesPerCycle << CONFIG_MAX_PITCH) + 3; |
const uint neededSilenceSamples = (maxSamplesPerCycle << CONFIG_MAX_PITCH) + 3; |
702 |
const uint currentlyCachedSilenceSamples = pSample->GetCache().NullExtensionSize / pSample->FrameSize; |
const uint currentlyCachedSilenceSamples = pSample->GetCache().NullExtensionSize / pSample->FrameSize; |
703 |
if (currentlyCachedSilenceSamples < neededSilenceSamples) { |
if (currentlyCachedSilenceSamples < neededSilenceSamples) { |
925 |
} |
} |
926 |
|
|
927 |
void InstrumentResourceManager::GigResourceManager::Destroy(::gig::File* pResource, void* pArg) { |
void InstrumentResourceManager::GigResourceManager::Destroy(::gig::File* pResource, void* pArg) { |
928 |
dmsg(1,("Freeing gig file from memory...")); |
dmsg(1,("Freeing gig file '%s' from memory ...", pResource->GetFileName().c_str())); |
929 |
|
|
930 |
// Delete as much as possible of the gig file. Some of the |
// Delete as much as possible of the gig file. Some of the |
931 |
// dimension regions and samples may still be in use - these |
// dimension regions and samples may still be in use - these |