--- linuxsampler/trunk/src/modulationsystem.cpp 2004/01/18 20:31:31 31 +++ linuxsampler/trunk/src/modulationsystem.cpp 2004/02/03 13:21:19 32 @@ -25,6 +25,7 @@ float** ModulationSystem::pDestinationParameter = NULL; uint ModulationSystem::uiSampleRate; uint ModulationSystem::uiMaxSamplesPerCycle; +ModulationSystem::__FragmentTime__ ModulationSystem::FragmentTime; void ModulationSystem::Initialize(uint SampleRate, uint MaxSamplesPerCycle) { ModulationSystem::uiMaxSamplesPerCycle = MaxSamplesPerCycle; @@ -36,6 +37,7 @@ pDestinationParameter[i] = pDestinationParameter[i - 1] + MaxSamplesPerCycle; } } + ModulationSystem::FragmentTime.end = ModulationSystem::CreateTimeStamp(); } void ModulationSystem::Close() { @@ -52,3 +54,58 @@ void ModulationSystem::ResetDestinationParameter(ModulationSystem::destination_t dst, float val) { for (int i = 0; i < uiMaxSamplesPerCycle; i++) pDestinationParameter[dst][i] = val; } + +/** + * Updates the time stamps for the beginning and end of the current audio + * fragment. This is needed to be able to calculate the respective sample + * point later for which an event belongs to. + */ +void ModulationSystem::UpdateFragmentTime() { + // update time stamp for this audio fragment cycle + ModulationSystem::FragmentTime.begin = ModulationSystem::FragmentTime.end; + ModulationSystem::FragmentTime.end = ModulationSystem::CreateTimeStamp(); + + // recalculate sample ratio for this audio fragment + real_time_t fragmentDuration = ModulationSystem::FragmentTime.end - ModulationSystem::FragmentTime.begin; + ModulationSystem::FragmentTime.sample_ratio = (float) ModulationSystem::uiMaxSamplesPerCycle / (float) fragmentDuration; +} + +/** + * Creates a real time stamp for the current moment. Out of efficiency this + * is implemented in inline assembly for each CPU independently; we currently + * don't use a generic solution for CPUs that are not yet covered by the + * assembly code, instead an error message is prompted on compile time, forcing + * the user to contact us. + */ +ModulationSystem::real_time_t ModulationSystem::CreateTimeStamp() { + #if defined(__i386__) || defined(__x86_64__) + uint64_t t; + __asm__ __volatile__ ("rdtsc" : "=A" (t)); + return t >> 8; + #elif defined(__ia64__) + real_time_t t; + __asm__ __volatile__ ("mov %0=ar.itc" : "=r"(t)); + return t; + #elif defined(__powerpc__) + real_time_t t; + __asm__ __volatile__ ( + "98: mftb %0\n" + "99:\n" + ".section __ftr_fixup,\"a\"\n" + " .long %1\n" + " .long 0\n" + " .long 98b\n" + " .long 99b\n" + ".previous" + : "=r" (t) : "i" (0x00000100) + ); + return t; + #elif defined(__alpha__) + real_time_t t; + __asm__ __volatile__ ("rpcc %0" : "=r"(t)); + return t; + #else // we don't want to use a slow generic solution + # error Sorry, LinuxSampler lacks time stamp code for your system. + # error Please report this error and the CPU you are using to the LinuxSampler developers mailing list! + #endif +}