<div dir="ltr">Hi Sebastian.<br><div class="gmail_extra"><br></div><div class="gmail_extra">Thanks for answering.<br><br></div><div class="gmail_extra"><div class="gmail_quote">On Wed, Jul 6, 2016 at 8:13 AM, Sebastian Dröge <span dir="ltr"><<a href="mailto:sebastian@centricular.com" target="_blank">sebastian@centricular.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class="">On Di, 2016-07-05 at 15:43 +0200, Peter Maersk-Moller wrote:<br>
> But to no avail. So I can declare an 8 byte accumulator, I just can't<br>
> accumulate in it? Is that the case?<br>
</span>There's no 64 bit accumulator opcode, correct:<br>
<a href="https://gstreamer.freedesktop.org/data/doc/orc/orc-opcodes.html" rel="noreferrer" target="_blank">https://gstreamer.freedesktop.org/data/doc/orc/orc-opcodes.html</a><br>
<br>
accw, accl and accsadubl are the only ones currently. Adding new ones<br>
shouldn't be that much effort though, as long as it can be implemented<br>
at least for SSE and NEON.<br></blockquote><br></div><div class="gmail_quote">It ought to be trivial, however it might not provide any speedup. The devil is in the details.<br><br></div><div class="gmail_quote">That said, it it possible to emulate the 8 byte accumulator. Here is an example. The original C-code (simplified - no checks) is this where <i>buf->rms[i]</i> are unsigned 64 bit integer and the result is RMS squared (ie. you need to take the square root):<br><br><span style="font-family:monospace,monospace">void MakeRMS(audio_buffer_t* buf) {<br>        u_int32_t samples_per_channel = buf->len /<br>                  (sizeof(int32_t) * buf->channels);<br>        for (u_int32_t i=0 ; i < buf->channels; i++) {<br>                buf->rms[i] = 0;<br>                int32_t* sample = ((int32_t*)buf->data) + i;<br>                for (u_int32_t j=0; j < samples_per_channel ; j++) {<br>                        buf->rms[i] += ((*sample)*(*sample));<br>                        sample += buf->channels;<br>                }<br>                buf->rms[i] /= samples_per_channel;<br>        }</span><br>}<br><br></div><div class="gmail_quote">In Orc, where buf->channels == 1, the inner loop can be replaced with this Orc function (on Little Endian Hardware) taking into account that each sample is 16 bit signed integer values in a signed 32 bit integer<br><br></div><div class="gmail_quote"><span style="font-family:monospace,monospace">.function audio_rms_orc_one_channel<br>.source 4 src int32_t<br>.accumulator 4 lowres<br>.accumulator 4 highres<br>.temp 4 squared<br>.temp 2 low2<br>.temp 2 high2<br>.temp 4 low4<br>.temp 4 high4<br>mulll     squared src src<br>select0lw low2 squared<br>select1lw high2 squared<br>convuwl   low4 low2<br>convuwl   high4 high2<br>accl      lowres low4<br>accl      highres high4<br></span><br></div><div class="gmail_quote">Then the squared RMS value can be calculated as <br></div><div class="gmail_quote"><br><div style="margin-left:40px">buf->rms[0] = (low_rms +(((u_int64_t)high_rms)<<16))/samples_per_channel;<br></div><br></div><div class="gmail_quote">Howerver, this Orc code is slower 9 out of 10 times when calculated on 2048 samples arrays and measured with gettimeofday() (not the optimal way - I know - but it gives you a hint with certain limitations) on an older dual core laptop. So developing a RMS function for multiple channels interleaved, has kind of no purpose. Of course if most of these commands could be replaced by a SSE/NEON instruction saving a 4 byte integer to an 8 byte accumulator, timing might improve ... maybe ...<br><br></div><div class="gmail_quote">Anyway, does GStreamer implement Orc code for audio manipulation and if yes, have you measured that it is actually worth it? I tried to see if GStreamer has an RMS module, but it appear that it does not (or I just haven't looked close enough).<br><br></div><div class="gmail_quote">Best regards<br></div><div class="gmail_quote">Peter<br></div></div></div>