<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <meta content="text/html; charset=ISO-8859-1"
      http-equiv="Content-Type">
    <title></title>
  </head>
  <body text="#000000" bgcolor="#ffffff">
    Paul<br>
    <br>
    Thank you for the explanations. I have data running right through
    the app now using a simulator in Erlang pretending to be the
    hardware. Next up is to plug in the DSP. I've done a linked-in
    driver before so hoping that won't be too difficult. <br>
    <br>
    Bob<br>
    <br>
    On 23/03/2011 01:50, Per Gustafsson wrote:
    <blockquote
      cite="mid:AANLkTinruhUL_BV04m0Qti0eAavp1VEFkU75SFVP+qRh@mail.gmail.com"
      type="cite">So essentially everytime this function is called one
      of the four clauses will match
      <div><br>
      </div>
      <div>1. Will match if the state is exactly a full block right now.
        It will send that frame to the dsp module, and then it will
        continue to decode the current frame using a new state.</div>
      <div><br>
      </div>
      <div>2. If the current state is larger than a full block we will
        split out the full block and send that to the dsp module, we
        will then continue to decode the current frame using whatever
        was left in the old state as the new state.</div>
      <div><br>
      </div>
      <div>3. If the frame still has samples in it and neither of the
        first two cases were true we will take out one set of samples,
        convert to them to floats and add them to the end of the state
        and continue to decode the rest of the frame.</div>
      <div><br>
      </div>
      <div>4 If the frame is empty we will return the current state.</div>
      <div><br>
      </div>
      <div>The difference between this version and the version that uses
        a comprehension is that we are checking for every sample whether
        the state is now a full frame or not.</div>
      <div><br>
      </div>
      <div>This allows us to write the new samples directly into the
        state binary, rather than creating a temporary binary. That we
        then copy into the state binary.</div>
      <div><br>
        <br>
        <div class="gmail_quote">2011/3/18 Bob Cowdery <span dir="ltr"><<a
              moz-do-not-send="true"
              href="mailto:bob@bobcowdery.plus.com" target="_blank">bob@bobcowdery.plus.com</a>></span><br>
          <blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt
            0.8ex; border-left: 1px solid rgb(204, 204, 204);
            padding-left: 1ex;">
            <div text="#000000" bgcolor="#ffffff"> Humour me. I'm still
              learning erlang and it still takes me ages to write a few
              lines at times. Comments in-line.<br>
              <br>
              Bob
              <div><br>
                <br>
                On 17/03/2011 20:54, Per Gustafsson wrote:
                <blockquote type="cite"><font face="'courier new',
                    monospace">You're right it should be as below to get
                    the same behaviour, but I think it will work the
                    same for input that makes sense.</font>
                  <div><font face="'courier new', monospace"><br>
                    </font></div>
                </blockquote>
              </div>
              Straight forward
              <div><br>
                <blockquote type="cite">
                  <div><font face="'courier new', monospace"> </font></div>
                  <div><font face="'courier new', monospace"> <span
                        style="border-collapse: collapse; font-size:
                        13px;">
                        <div style="color: rgb(80, 0, 80);">
                          do_decode_frame(Frame, State) -><br>
                             %% Separate the command bytes from the
                          frame data<br>
                             <<C1:8, C2:8, C3:8, C4:8, C5:8,
                          Rest/binary>> = Frame,<br>
                        </div>
                           decode_samples(Rest, State).</span></font></div>
                  <div><font face="'courier new', monospace"><span
                        style="border-collapse: collapse; font-size:
                        13px;"><br>
                      </span></font></div>
                </blockquote>
              </div>
              First clause will match a full block where frames and
              blocks are aligned. Never happen in practice as 63 will
              never be a multiple of 64 but it's right that the code
              should not know this.
              <div><br>
                <blockquote type="cite">
                  <div><font face="'courier new', monospace"><span
                        style="border-collapse: collapse; font-size:
                        13px;"> decode_samples(Frame, FullBlock) when
                        bytesize(FullBlock) == ?BinSize -><br>
                          dsp:process_block(FullBlock),<br>
                          decode_samples(Frame, <<>>);<br>
                      </span></font></div>
                </blockquote>
              </div>
              Second clause will match when a FullBlock has > <font
                face="'courier new', monospace"><span
                  style="border-collapse: collapse; font-size: 13px;"><span
                    style="font-family: arial,sans-serif;"><span
                      style="font-family: 'courier new',monospace;
                      color: rgb(0, 0, 0);">?BinSize and will split into
                    </span></span></span></font><font face="'courier
                new', monospace"><span style="border-collapse: collapse;
                  font-size: 13px;"><span style="font-family:
                    arial,sans-serif;"><span style="font-family:
                      'courier new',monospace; color: rgb(0, 0, 0);">?BinSize
                      and Rest<br>
                    </span></span></span></font>
              <div>
                <blockquote type="cite">
                  <div><font face="'courier new', monospace"><span
                        style="border-collapse: collapse; font-size:
                        13px;"> <span style="font-family:
                          arial,sans-serif;">
                          <div style="color: rgb(80, 0, 80);"> <span
                              style="font-family: 'courier
                              new',monospace; color: rgb(0, 0, 0);">decode_samples(Frame,

                              <<FullBlock:?BinSize/binary,
                              Rest/binary>>) -><br>
                                dsp:process_block(FullBlock),<br>
                                decode_samples(Frame, Rest);</span></div>
                        </span></span></font></div>
                </blockquote>
              </div>
              Third clause. Now I get lost. This will match pretty much
              any binary > 8 bytes and any State. So this will get
              called from first and second clause. The next two clauses
              seem to run into each other. Don't understand that. Is the
              binary comprehension hidden somewhere in there?
              <div><br>
              </div>
            </div>
          </blockquote>
          <div><br>
          </div>
          <div>Sorry the third clause is totally wrong. It should have
            been:<br>
            <font face="'courier new', monospace"><span
                style="border-collapse: collapse; font-size: 13px;">decode_samples(<<I:24/big-signed,

                Q:24/big-signed, _M:16/big-signed, Rest/binary>>,
                State) -><br>
                  decode_samples(Rest,
                <<State/binary, (I/?S):32/float,
                (Q/?S):32/float>>);</span></font><br>
          </div>
          <blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt
            0.8ex; border-left: 1px solid rgb(204, 204, 204);
            padding-left: 1ex;">
            <div text="#000000" bgcolor="#ffffff">
              <div>
                <blockquote type="cite">
                  <div><font face="'courier new', monospace"><span
                        style="border-collapse: collapse; font-size:
                        13px;">decode_samples(<<I:24/big-signed,
                        Q:24/big-signed, _M:16/big-signed,<br>
                        Rest/binary>>, State) -><br>
                          decode_samples(<<State/binary, (I/?S):32/float,

                        (Q/?S):32/float>>;<br>
                        decode_samples(<<>>, State) -><br>
                         {ok, State}.</span></font></div>
                  <div><font face="arial, sans-serif"><span
                        style="border-collapse: collapse;"><br>
                      </span></font></div>
                </blockquote>
              </div>
              Would this work as the last two clauses:<br>
              decode_samples(Frame, State) -><br>
                  decode_samples(<<>>, <<
              State/binary, <<(I/?S):32/float,
              (Q/?S):32/float>> || <<I:24/big-signed,
              Q:24/big-signed, _M:16/big-signed>> <= Frame
              >>)
              <div>
                <div><br>
                  decode_samples(<<>>, State) -><br>
                       {ok, State}.<br>
                  <blockquote type="cite">
                    <div><br>
                      2011/3/17 Bob Cowdery <<a
                        moz-do-not-send="true"
                        href="mailto:bob@bobcowdery.plus.com"
                        target="_blank">bob@bobcowdery.plus.com</a>>:<br>
                      > Thanks. More or less what I thought that the
                      only copy is in the append<br>
                      > operation. The one liner is the big one in
                      terms of time but I will<br>
                      > profile the whole thing eventually. I don't
                      think your solution does<br>
                      > quite the same thing as the sent block must
                      be exactly the correct size<br>
                      > not >= but I appreciate the kind of
                      structure you are using with small<br>
                      > clauses is more elegant.<br>
                      ><br>
                      > Bob<br>
                      ><br>
                      > On 17/03/2011 17:11, Per Gustafsson wrote:<br>
                      >> It will copy binaries, but essentially
                      the state binary will act like<br>
                      >> a growable array, pre-allocating space to
                      grow in, so there will be<br>
                      >> some copying , but it will be linear in
                      the size of the resulting<br>
                      >> array.<br>
                      >> It might be a little bit faster to
                      rewrite this as shown below. The<br>
                      >> reason I think this might be faster is
                      that you do not create a<br>
                      >> temporary samples array that just gets
                      copied. Whether this is faster<br>
                      >> or not in reality is of course a matter
                      of benchmarking.<br>
                      >><br>
                      >> %% Constants<br>
                      >> %% Input scale factor<br>
                      >> -define (S, (1 bsl 23) - 1).<br>
                      >> %% Block size for DSP (interleaved I and
                      Q)<br>
                      >> -define (BlockSz, 1024).<br>
                      >> %% Samples in a Metis frame (interleaved
                      I and Q)<br>
                      >> -define (MetisSmpls, 63).<br>
                      >> %% Bytes in a float<br>
                      >> -define (FloatSz, 4).<br>
                      >> %% Size of binary for given block size<br>
                      >> -define (BinSz,
                      ?BlockSz*2*?FloatSz*?MetisSmpls).<br>
                      >><br>
                      >> do_decode_frame(Frame, State) -><br>
                      >>    %% Separate the command bytes from the
                      frame data<br>
                      >>    <<C1:8, C2:8, C3:8, C4:8, C5:8,
                      Rest/binary>> = Frame,<br>
                      >>    decode_samples(Rest, State).<br>
                      >><br>
                      >> decode_samples(Frame, State) when
                      size(State) >= ?BinSz -><br>
                      >>   dsp:process_block(State),<br>
                      >>   decode_samples(Frame,
                      <<>>);<br>
                      >> decode_samples(<<I:24/big-signed,
                      Q:24/big-signed, _M:16/big-signed,<br>
                      >> Rest/binary>>, State) -><br>
                      >>   decode_samples(<<State/binary,
                      (I/?S):32/float, (Q/?S):32/float>>;<br>
                      >> decode_samples(<<>>, State)
                      -><br>
                      >>   {ok, State}.<br>
                      >><br>
                      >> 2011/3/17 Bob Cowdery <<a
                        moz-do-not-send="true"
                        href="mailto:bob@bobcowdery.plus.com"
                        target="_blank">bob@bobcowdery.plus.com</a>><br>
                      >>> Hi,<br>
                      >>><br>
                      >>> Am I correct in thinking that the
                      code fragments below will not copy any<br>
                      >>> binary data. I've not tested the
                      function yet so it may have bugs but<br>
                      >>> I'm interested in whether it will be
                      optimal in efficiency. State starts<br>
                      >>> off as an empty binary. Frames are
                      decoded and placed in a block. There<br>
                      >>> are not an integral number of frames
                      to a block. The function<br>
                      >>> dsp:process_block() is in another
                      gen-server.<br>
                      >>><br>
                      >>> Thanks<br>
                      >>> Bob<br>
                      >>><br>
                      >>> %% Constants<br>
                      >>> %% Input scale factor<br>
                      >>> -define (S, (1 bsl 23) - 1).<br>
                      >>> %% Block size for DSP (interleaved I
                      and Q)<br>
                      >>> -define (BlockSz, 1024).<br>
                      >>> %% Samples in a Metis frame
                      (interleaved I and Q)<br>
                      >>> -define (MetisSmpls, 63).<br>
                      >>> %% Bytes in a float<br>
                      >>> -define (FloatSz, 4).<br>
                      >>> %% Size of binary for given block
                      size<br>
                      >>> -define (BinSz,
                      ?BlockSz*2*?FloatSz*?MetisSmpls).<br>
                      >>><br>
                      >>> do_decode_frame(Frame, State) -><br>
                      >>>    %% Separate the command bytes from
                      the frame data<br>
                      >>>    <<C1:8, C2:8, C3:8, C4:8,
                      C5:8, Rest/binary>> = Frame,<br>
                      >>>    %% What's left now is
                      <<I:24, Q:24, M:16 ..repeated 63 times..
                      >><br>
                      >>>    %% This one liner converts the I
                      and Q to scaled floats<br>
                      >>>    Samples = <<
                      <<(I/?S):32/float, (Q/?S):32/float>>
                      ||<br>
                      >>> <<I:24/big-signed,
                      Q:24/big-signed, _M:16/big-signed>> <=
                      Rest >>,<br>
                      >>>    CurrentSz = size(State),<br>
                      >>>    FrameSz = size(Samples),<br>
                      >>>    if<br>
                      >>>        (CurrentSz + FrameSz) <
                      ?BinSz -><br>
                      >>>            NewState =
                      <<State/binary, Samples/binary>>;<br>
                      >>>        true -><br>
                      >>>            %% Binary part of this
                      transfer<br>
                      >>>            CutAt = ?BinSz - CurrentSz
                      - 1,<br>
                      >>>            Bp = binary_part(Samples,
                      {0, CutAt}),<br>
                      >>>            %% Binary part of
                      remainder<br>
                      >>>            Br = binary_part(Samples,
                      {CutAt, FrameSz - CutAt}),<br>
                      >>>            %% Process this block<br>
                      >>>          
                       dsp:process_block(<<State/binary,
                      Bp/binary>>),<br>
                      >>>            NewState = Br<br>
                      >>>    end,<br>
                      >>>    {ok, NewState}.<br>
                      >>><br>
                      >>>
                      ________________________________________________________________<br>
                      >>> erlang-questions (at) <a
                        moz-do-not-send="true" href="http://erlang.org"
                        target="_blank">erlang.org</a> mailing list.<br>
                      >>> See <a moz-do-not-send="true"
                        href="http://www.erlang.org/faq.html"
                        target="_blank">http://www.erlang.org/faq.html</a><br>
                      >>> To unsubscribe; mailto:<a
                        moz-do-not-send="true"
                        href="mailto:erlang-questions-unsubscribe@erlang.org"
                        target="_blank">erlang-questions-unsubscribe@erlang.org</a><br>
                      >>><br>
                      ><br>
                      ><br>
                      <br>
                    </div>
                  </blockquote>
                  <br>
                </div>
              </div>
            </div>
          </blockquote>
        </div>
        <br>
      </div>
    </blockquote>
    <br>
  </body>
</html>