Poor mans jcm800?

I love the jcm800pre but it is very resource hungry. Has anyone found an alternative setup that sounds similar but less resource hungry?

Hi

The jcm800 is a complex analogue simulation, hence it needs more Power then other Amp simulations. The MOD version comes already with a reduced quality to be able to handle the CPU request of this plug.
Poor man’s solution may be C* AmpVTS with a Cabinet simulator, or GxAmplifier. Both have a jcm800 stage, as far I remember.

2 Likes

There are quite a few amp sims that have marshall options
Hook it to a cab sim (if needed) and tweak it till you have the sound you want

2 Likes

I nearly hit 100% on my mod with a simple jcm800 feeding into a vintage cab set to marshall and then into a simple plate reverb.

My solution has been to switch to 256 frames per cycle.

I guess the Dwarf will handle that a bit better.

By the way, is there a way for the plugin to know which device it’s being run on, in order to adapt its features to the power available ?

You know this at compile time.

We have this little tester code on our build pipeline, which basically does a check that everything is as expected.

/* buildroot-flags-tester
 *  simple code to check for enabled optimizations
 *  does not need to be run, we can check for optimizations via compiler macros
 */

// These macros must always be defined by the compiler
#ifndef __GNUC__
#error __GNUC__ not defined
#endif
#ifndef __GNUC_MINOR__
#error __GNUC_MINOR__ not defined
#endif
#ifndef __GNUC_PATCHLEVEL__
#error __GNUC_PATCHLEVEL__ not defined
#endif
#ifndef __BYTE_ORDER__
#error __BYTE_ORDER__ not defined
#endif
#ifndef __ORDER_LITTLE_ENDIAN__
#error __ORDER_LITTLE_ENDIAN__ not defined
#endif
#ifndef __linux
#error __linux not defined
#endif
#ifndef __linux__
#error __linux__ not defined
#endif
#ifndef __unix__
#error __unix__ not defined
#endif

// Check minimum compiler version
#if (__GNUC__ * 100 + __GNUC_MINOR__) < 409
#error compiler is too old
#endif

// Check if cross-compiling
#if ! (defined(__arm__) || defined(__aarch64__))
#error not cross-compiling
#endif

// Check if our custom flags are being used
#ifndef __MOD_DEVICES__
#error __MOD_DEVICES__ not defined
#endif

// Test for little endian
#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
#error __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
#endif

// Check for expected flags under 32bit
#ifdef __arm__

#ifndef __ARMEL__
#error __ARMEL__ not defined
#endif
#ifndef __ARM_ARCH
#error __ARM_ARCH not defined
#endif
#ifndef __ARM_ARCH_7A__
#error __ARM_ARCH_7A__ not defined
#endif
#ifndef __ARM_EABI__
#error __ARM_EABI__ not defined
#endif
#ifndef __ARM_FEATURE_SIMD32
#error __ARM_FEATURE_SIMD32 not defined
#endif
#ifndef __ARM_NEON__
#error __ARM_NEON__ not defined
#endif
#ifndef __ARM_NEON
#error __ARM_NEON not defined
#endif
#ifndef __ARM_NEON_FP
#error __ARM_NEON_FP not defined
#endif
#ifndef __VFP_FP__
#error __VFP_FP__ not defined
#endif

#if __ARM_ARCH != 7
#error __ARM_ARCH != 7
#endif
#if __ARM_EABI__ != 1
#error __ARM_EABI__ != 1
#endif
#if __ARM_NEON_FP != 6
#error __ARM_NEON_FP != 6 (neon-vfpv4)
#endif

#ifdef __arm64__
#error __arm64__ defined
#endif
#ifdef __aarch64__
#error __aarch64__ defined
#endif
#ifdef __ARM_ARCH_8
#error __ARM_ARCH_8 defined
#endif
#ifdef __ARM_ARCH_8A
#error __ARM_ARCH_8A defined
#endif
#ifdef _LP64
#error _LP64 defined
#endif
#ifdef __LP64__
#error __LP64__ defined
#endif

#endif

// Check for expected flags under 64bit
#ifdef __aarch64__

#ifndef __ARM_ARCH
#error __ARM_ARCH not defined
#endif
#ifndef __ARM_ARCH_8A
#error __ARM_ARCH_8A not defined
#endif
#ifndef __ARM_NEON
#error __ARM_NEON not defined
#endif
#ifndef _LP64
#error _LP64 not defined
#endif
#ifndef __LP64__
#error __LP64__ not defined
#endif

#if __ARM_ARCH != 8
#error __ARM_ARCH != 8
#endif

#ifdef __arm
#error __arm defined
#endif
#ifdef __arm__
#error __arm__ defined
#endif
#ifdef __ARMEL__
#error __ARMEL__ defined
#endif
#ifdef __ARM_ARCH_7A__
#error __ARM_ARCH_7A__ defined
#endif

#endif

// define entry point, so we can build this code
int main() { return 0; }

So just checking for armv7 vs aarch64 is possible to differentiate duo vs duox.
For duox vs dwarf, not sure yet. But the CPU is different, so likely GCC exposes some different macros.
In our cloud builder and mod-plugin-builder, we always use GCC4.9 for duo and duox, and GCC7 for dwarf. So we can check for that as last resort.

If you really need to do it on runtime in a generic application binary (or scripting language) you can open /etc/mod-hardware-descriptor.json and find some useful info in there.

Wouldn’t it be easier for developers that you define an extra macro corresponding to either DUO DWARF or DUOX

well yes. it was not too much of a problem for duo vs duox, but for the dwarf it makes sense