dsp::AudioBlock - converting float<->double during copying possible?

copyFrom has a template parameter ‘OtherSampleType’, should it be possible to copy from a double buffer to a float buffer (or vice versa) ?

This doesn’t compile:

    juce::AudioBuffer<double> sourceData(1, 1000);
    juce::dsp::AudioBlock<double> source(sourceData);

    juce::AudioBuffer<float> destData(1, 1000);
    juce::dsp::AudioBlock<float> dest(destData);
    
    dest.copyFrom<double>(source);

Output:

1>Main.cpp
1>C:\Users\user\dev\juce\modules\juce_dsp\containers\juce_AudioBlock.h(624,1): error C2665: 'juce::detail::FloatVectorOperationsBase<float,int>::copy': none of the 4 overloads could convert all the argument types
1>C:\Users\user\dev\juce\modules\juce_audio_basics\buffers\juce_FloatVectorOperations.h(44,31): message : could be 'void juce::detail::FloatVectorOperationsBase<float,size_t>::copy(FloatType *,const FloatType *,CountType) noexcept'
1>        with
1>        [
1>            FloatType=float,
1>            CountType=size_t
1>        ]
1>C:\Users\user\dev\juce\modules\juce_audio_basics\buffers\juce_FloatVectorOperations.h(44,31): message : or       'void juce::detail::FloatVectorOperationsBase<double,size_t>::copy(FloatType *,const FloatType *,CountType) noexcept'
1>        with
1>        [
1>            FloatType=double,
1>            CountType=size_t
1>        ]
1>C:\Users\user\dev\juce\modules\juce_audio_basics\buffers\juce_FloatVectorOperations.h(44,31): message : or       'void juce::detail::FloatVectorOperationsBase<double,int>::copy(FloatType *,const FloatType *,CountType) noexcept'
1>        with
1>        [
1>            FloatType=double,
1>            CountType=int
1>        ]
1>C:\Users\user\dev\juce\modules\juce_audio_basics\buffers\juce_FloatVectorOperations.h(44,31): message : or       'void juce::detail::FloatVectorOperationsBase<float,int>::copy(FloatType *,const FloatType *,CountType) noexcept'
1>        with
1>        [
1>            FloatType=float,
1>            CountType=int
1>        ]
1>C:\Users\user\dev\juce\modules\juce_dsp\containers\juce_AudioBlock.h(624,1): message : while trying to match the argument list '(float *, double *, Type)'
1>        with
1>        [
1>            Type=size_t
1>        ]
1>C:\Users\user\dev\juce\modules\juce_dsp\containers\juce_AudioBlock.h(314): message : see reference to function template instantiation 'void juce::dsp::AudioBlock<float>::copyFromInternal<double>(const juce::dsp::AudioBlock<double> &) noexcept const' being compiled
1>C:\Users\user\dev\juce\modules\juce_dsp\containers\juce_AudioBlock.h(314): message : see reference to function template instantiation 'void juce::dsp::AudioBlock<float>::copyFromInternal<double>(const juce::dsp::AudioBlock<double> &) noexcept const' being compiled
1>C:\Users\user\dev\test\testAudioBlock\NewProject\Source\Main.cpp(22): message : see reference to function template instantiation 'juce::dsp::AudioBlock<float> &juce::dsp::AudioBlock<float>::copyFrom<double>(const juce::dsp::AudioBlock<double> &) noexcept' being compiled
1>C:\Users\user\dev\test\testAudioBlock\NewProject\Source\Main.cpp(22): message : see reference to function template instantiation 'juce::dsp::AudioBlock<float> &juce::dsp::AudioBlock<float>::copyFrom<double>(const juce::dsp::AudioBlock<double> &) noexcept' being compiled

You can use makeCopyOf for that functionality

EDIT: Whoops. Noticed you meant AudioBlock and not AudioBuffer.
I think you’d have to just use FloatVectorOperations::copy on each channel and reinterpret_cast<const double*> each read pointer

Thanks, but I looks to me there are no FloatVectorOperations::copy operations which support multiple types. Looks like I need to do it by myself.

This

FloatVectorOperations::copy(dest.getChannelPointer(0), reinterpret_cast<const double*>(source.getChannelPointer(0), source.getNumSamples());
FloatVectorOperations::copy(dest.getChannelPointer(1), reinterpret_cast<const double*>(source.getChannelPointer(1), source.getNumSamples());

or this

dest.copyFrom(0, 0, reinterpret_cast<const double*>(source.getChannelPointer(0)), source.getNumSamples());
etc...

should compile and work.

thanks, but how should this work? It makes no sense to me. If I reinterpret double to const double ::copy still has no overloads for this, because source and destination in the template definition have the same type.

Or do you mean to reinterpret the source double-pointer, as a pointer to floats, then again the pointer (physically) still points to doubles, which will bit-split any double into of two floats, which of course will create wrong values.

What I instead want is a simd optimised version of something like this

    for (int i = 0; i < size; ++i)
                    destSamples[i] = static_cast<float> (srcSamples[i]);

…but it seems there is nothing like this in juce.

My bad, I mixed up which blocks are which data types.

Also, according to this stackoverflow post, I was wrong and you were right about bit-splitting with the different-sized pointers. So you’d probably need to get down on a per-sample level and static_cast each sample.

And by SIMD-optimized, you mean that you’d be working with conversion between two SIMD buffers?

with SIMD-optimized I mean, to use special instructions like SSE for x64, to improve the conversion performance.

floatdouble: _mm_cvtps_pd

doublefloat: _mm_cvtpd_ps

PS:
found this example code