<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ca">
	<id>http://wiki.joanillo.org/index.php?action=history&amp;feed=atom&amp;title=Circular_buffer_%2F_Ringbuffer</id>
	<title>Circular buffer / Ringbuffer - Historial de revisió</title>
	<link rel="self" type="application/atom+xml" href="http://wiki.joanillo.org/index.php?action=history&amp;feed=atom&amp;title=Circular_buffer_%2F_Ringbuffer"/>
	<link rel="alternate" type="text/html" href="http://wiki.joanillo.org/index.php?title=Circular_buffer_/_Ringbuffer&amp;action=history"/>
	<updated>2026-08-30T09:20:11Z</updated>
	<subtitle>Historial de revisió per a aquesta pàgina del wiki</subtitle>
	<generator>MediaWiki 1.34.2</generator>
	<entry>
		<id>http://wiki.joanillo.org/index.php?title=Circular_buffer_/_Ringbuffer&amp;diff=248971&amp;oldid=prev</id>
		<title>Joan: /* JACK i Ringbuffer */</title>
		<link rel="alternate" type="text/html" href="http://wiki.joanillo.org/index.php?title=Circular_buffer_/_Ringbuffer&amp;diff=248971&amp;oldid=prev"/>
		<updated>2012-02-28T00:06:25Z</updated>

		<summary type="html">&lt;p&gt;&lt;span dir=&quot;auto&quot;&gt;&lt;span class=&quot;autocomment&quot;&gt;JACK i Ringbuffer&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Pàgina nova&lt;/b&gt;&lt;/p&gt;&lt;div&gt;__TOC__&lt;br /&gt;
=Què és un ringbuffer=&lt;br /&gt;
*http://en.wikipedia.org/wiki/Circular_buffer&lt;br /&gt;
És un buffer circular, és a dir, allà on acaba comença. S'utilitza amb streaming i aplicacions d'audio i video. Imaginem que volem bolcar el buffer que ve de la targeta de so (del micro) al buffer de la nostra aplicació, i això passa a cada callback. Utilitzant un ringbuffer ens evitem de reposicionar l'index i d'esborrar el contingut. El contingut es va matxacant automàticament.&lt;br /&gt;
&lt;br /&gt;
En l'article de la wikipedia s'entén bé, i hi ha un exemple que funciona i s'entén de com opera el ringbuffer:&lt;br /&gt;
*http://en.wikipedia.org/wiki/Circular_buffer#Always_Keep_One_Slot_Open&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* Circular buffer example, keeps one slot open */&lt;br /&gt;
 &lt;br /&gt;
// $ g++ -Wall -o ringbuffer ringbuffer.cpp &lt;br /&gt;
// $ ./ringbuffer &lt;br /&gt;
// 20&lt;br /&gt;
// 21&lt;br /&gt;
// 22&lt;br /&gt;
// 23&lt;br /&gt;
// 24&lt;br /&gt;
// 25&lt;br /&gt;
// 26&lt;br /&gt;
// 27&lt;br /&gt;
// 28&lt;br /&gt;
// 29&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;malloc.h&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
/* Opaque buffer element type.  This would be defined by the application. */&lt;br /&gt;
typedef struct { int value; } ElemType;&lt;br /&gt;
 &lt;br /&gt;
/* Circular buffer object */&lt;br /&gt;
typedef struct {&lt;br /&gt;
    int         size;   /* maximum number of elements           */&lt;br /&gt;
    int         start;  /* index of oldest element              */&lt;br /&gt;
    int         end;    /* index at which to write new element  */&lt;br /&gt;
    ElemType   *elems;  /* vector of elements                   */&lt;br /&gt;
} CircularBuffer;&lt;br /&gt;
 &lt;br /&gt;
void cbInit(CircularBuffer *cb, int size) {&lt;br /&gt;
    cb-&amp;gt;size  = size + 1; /* include empty elem */&lt;br /&gt;
    cb-&amp;gt;start = 0;&lt;br /&gt;
    cb-&amp;gt;end   = 0;&lt;br /&gt;
    cb-&amp;gt;elems = (ElemType *)calloc(cb-&amp;gt;size, sizeof(ElemType));&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
void cbFree(CircularBuffer *cb) {&lt;br /&gt;
    free(cb-&amp;gt;elems); /* OK if null */ }&lt;br /&gt;
 &lt;br /&gt;
int cbIsFull(CircularBuffer *cb) {&lt;br /&gt;
    return (cb-&amp;gt;end + 1) % cb-&amp;gt;size == cb-&amp;gt;start; }&lt;br /&gt;
 &lt;br /&gt;
int cbIsEmpty(CircularBuffer *cb) {&lt;br /&gt;
    return cb-&amp;gt;end == cb-&amp;gt;start; }&lt;br /&gt;
 &lt;br /&gt;
/* Write an element, overwriting oldest element if buffer is full. App can&lt;br /&gt;
   choose to avoid the overwrite by checking cbIsFull(). */&lt;br /&gt;
void cbWrite(CircularBuffer *cb, ElemType *elem) {&lt;br /&gt;
    cb-&amp;gt;elems[cb-&amp;gt;end] = *elem;&lt;br /&gt;
    cb-&amp;gt;end = (cb-&amp;gt;end + 1) % cb-&amp;gt;size;&lt;br /&gt;
    if (cb-&amp;gt;end == cb-&amp;gt;start)&lt;br /&gt;
        cb-&amp;gt;start = (cb-&amp;gt;start + 1) % cb-&amp;gt;size; /* full, overwrite */&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
/* Read oldest element. App must ensure !cbIsEmpty() first. */&lt;br /&gt;
void cbRead(CircularBuffer *cb, ElemType *elem) {&lt;br /&gt;
    *elem = cb-&amp;gt;elems[cb-&amp;gt;start];&lt;br /&gt;
    cb-&amp;gt;start = (cb-&amp;gt;start + 1) % cb-&amp;gt;size;&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
int main(int argc, char **argv) {&lt;br /&gt;
    CircularBuffer cb;&lt;br /&gt;
    ElemType elem = {0};&lt;br /&gt;
 &lt;br /&gt;
    int testBufferSize = 10; /* arbitrary size */&lt;br /&gt;
    cbInit(&amp;amp;cb, testBufferSize);&lt;br /&gt;
 &lt;br /&gt;
    /* Fill buffer with test elements 3 times */&lt;br /&gt;
    for (elem.value = 0; elem.value &amp;lt; 3 * testBufferSize; ++ elem.value)&lt;br /&gt;
        cbWrite(&amp;amp;cb, &amp;amp;elem);&lt;br /&gt;
 &lt;br /&gt;
    /* Remove and print all elements */&lt;br /&gt;
    while (!cbIsEmpty(&amp;amp;cb)) {&lt;br /&gt;
        cbRead(&amp;amp;cb, &amp;amp;elem);&lt;br /&gt;
        printf(&amp;quot;%d\n&amp;quot;, elem.value);&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
    cbFree(&amp;amp;cb);&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
El problema dels ringbuffer és que si l'index de End i de Start coincideixen, no sabem si el buffer està ple o buit. Per solucionar-ho hi ha varis mètodes, i el codi anterior respon al mètode ''Always keep one slot open'', que vol dir que sempre deixem una cel.la sense ocupar, i així podem saber quan el buffer està ple i quan està buit.&lt;br /&gt;
=JACK i Ringbuffer=&lt;br /&gt;
Harry Haaren:&lt;br /&gt;
*http://harryhaaren.blogspot.com/2011/11/tutorial-jack-ringbuffers.html&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
A quick tutorial on basic Jack ringbuffer usage. Ringbuffers are an easy way to exchange data from one thread&lt;br /&gt;
to another in a realtime safe way. This means that no thread will block when reading or writing, and hence&lt;br /&gt;
you use ringbuffers in a real-time thread.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*http://jackaudio.org/files/docs/html/ringbuffer_8h.html&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Functions&lt;br /&gt;
jack_ringbuffer_t * 	jack_ringbuffer_create (size_t sz)&lt;br /&gt;
void 	jack_ringbuffer_free (jack_ringbuffer_t *rb)&lt;br /&gt;
void 	jack_ringbuffer_get_read_vector (const jack_ringbuffer_t *rb, jack_ringbuffer_data_t *vec)&lt;br /&gt;
void 	jack_ringbuffer_get_write_vector (const jack_ringbuffer_t *rb, jack_ringbuffer_data_t *vec)&lt;br /&gt;
size_t 	jack_ringbuffer_read (jack_ringbuffer_t *rb, char *dest, size_t cnt)&lt;br /&gt;
size_t 	jack_ringbuffer_peek (jack_ringbuffer_t *rb, char *dest, size_t cnt)&lt;br /&gt;
void 	jack_ringbuffer_read_advance (jack_ringbuffer_t *rb, size_t cnt)&lt;br /&gt;
size_t 	jack_ringbuffer_read_space (const jack_ringbuffer_t *rb)&lt;br /&gt;
int 	jack_ringbuffer_mlock (jack_ringbuffer_t *rb)&lt;br /&gt;
void 	jack_ringbuffer_reset (jack_ringbuffer_t *rb)&lt;br /&gt;
size_t 	jack_ringbuffer_write (jack_ringbuffer_t *rb, const char *src, size_t cnt)&lt;br /&gt;
void 	jack_ringbuffer_write_advance (jack_ringbuffer_t *rb, size_t cnt)&lt;br /&gt;
size_t 	jack_ringbuffer_write_space (const jack_ringbuffer_t *rb)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Veiem que es pot fer tot allò que s'espera d'un buffer, com ara llegir, escriure, resetejar, alliberar.&lt;br /&gt;
&lt;br /&gt;
'''main.cpp'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ g++ main.cpp `pkg-config --cflags --libs jack`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
  Copyright (C) 2011 Harry van Haaren &amp;lt;harryhaaren@gmail.com&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  This program is free software: you can redistribute it and/or modify&lt;br /&gt;
  it under the terms of the GNU Lesser General Public License as published by&lt;br /&gt;
  the Free Software Foundation.&lt;br /&gt;
  &lt;br /&gt;
  This program is distributed in the hope that it will be useful,&lt;br /&gt;
  but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;
  GNU Lesser General Public License for more details.&lt;br /&gt;
  &lt;br /&gt;
  You should have received a copy of the GNU Lesser General Public License&lt;br /&gt;
  along with this program.  If not, see &amp;lt;http://www.gnu.org/licenses/&amp;gt;.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
// compile with:    g++ main.cpp `pkg-config --cflags --libs jack`&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;iostream&amp;gt;&lt;br /&gt;
#include &amp;lt;jack/jack.h&amp;gt;&lt;br /&gt;
#include &amp;lt;jack/ringbuffer.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// a global pointer to a ring buffer (usually a class will own this pointer)&lt;br /&gt;
jack_ringbuffer_t *buffer = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int write(int i)&lt;br /&gt;
{&lt;br /&gt;
  // get amount of space we can write&lt;br /&gt;
  int availableWrite = jack_ringbuffer_write_space(buffer);&lt;br /&gt;
  &lt;br /&gt;
  if (availableWrite &amp;gt;= sizeof(int))&lt;br /&gt;
  {&lt;br /&gt;
    // tell it to write data, keep track of how much was written&lt;br /&gt;
    int written = jack_ringbuffer_write( buffer, (const char*) &amp;amp;i , sizeof(int) );&lt;br /&gt;
    &lt;br /&gt;
    // ensure we wrote an entire event&lt;br /&gt;
    if (written != sizeof(int) ) {&lt;br /&gt;
      std::cout &amp;lt;&amp;lt; &amp;quot;ERROR! didn't write full integer!&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  else {&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;ERROR! RingBuffer FULL! Skipping...&amp;quot; &amp;lt;&amp;lt;std::endl;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int process(jack_nframes_t nframes, void* )&lt;br /&gt;
{&lt;br /&gt;
   // check if there's anything to read&lt;br /&gt;
  int availableRead = jack_ringbuffer_read_space(buffer);&lt;br /&gt;
  &lt;br /&gt;
  if ( availableRead &amp;gt;= sizeof(int) )&lt;br /&gt;
  {&lt;br /&gt;
    // create int to read value into&lt;br /&gt;
    int tempInt;&lt;br /&gt;
    &lt;br /&gt;
    // read from the buffer&lt;br /&gt;
    int result = jack_ringbuffer_read(buffer, (char*)&amp;amp;tempInt, sizeof(int));&lt;br /&gt;
    &lt;br /&gt;
    if ( result != sizeof(int) ) {&lt;br /&gt;
      std::cout &amp;lt;&amp;lt; &amp;quot;RtQueue::pull() WARNING! didn't read full event!&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
      return -1;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;Jack thread says int = &amp;quot; &amp;lt;&amp;lt; tempInt &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
  std::cout &amp;lt;&amp;lt; &amp;quot;Ring buffer tutorial&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
  &lt;br /&gt;
  // create an instance of a ringbuffer that will hold up to 20 integers,&lt;br /&gt;
  // let the pointer point to it&lt;br /&gt;
  buffer = jack_ringbuffer_create( 20 * sizeof(int));&lt;br /&gt;
  &lt;br /&gt;
  // lock the buffer into memory, this is *NOT* realtime safe, do it before&lt;br /&gt;
  // using the buffer!&lt;br /&gt;
  int res = jack_ringbuffer_mlock(buffer);&lt;br /&gt;
  &lt;br /&gt;
  // check if we've locked the memory successfully&lt;br /&gt;
  if ( res ) {&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;Error locking memory!&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    return -1;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  // create a JACK client, register the process callback and activate&lt;br /&gt;
  jack_client_t* client = jack_client_open ( &amp;quot;RingbufferDemo&amp;quot;, JackNullOption , 0 , 0 );&lt;br /&gt;
  jack_set_process_callback  (client, process , 0);&lt;br /&gt;
  jack_activate(client);&lt;br /&gt;
  &lt;br /&gt;
  for ( int i = 0; i &amp;lt; 1000; i++)&lt;br /&gt;
  {&lt;br /&gt;
    // write an event, then pause a while, JACK will get a go and then&lt;br /&gt;
    // we'll write another event... etc&lt;br /&gt;
    write(i);&lt;br /&gt;
    sleep(1);&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./a.out &lt;br /&gt;
Ring buffer tutorial&lt;br /&gt;
Jack thread says int = 0&lt;br /&gt;
Jack thread says int = 1&lt;br /&gt;
Jack thread says int = 2&lt;br /&gt;
Jack thread says int = 3&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
{{Autor}}, febrer 2012&lt;/div&gt;</summary>
		<author><name>Joan</name></author>
		
	</entry>
</feed>