AVR libc stdio missing ftell and fseek.

Go To Last Post
6 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Can anyone tell me why the ftell and fseek functions are missing from avr-libc's stdio? They are available in the AVR32 stdio. I've been trying to compile and run Ogg Vorbis' Tremor low-memory decoder on the XMEGA-A1 xplain board, just for giggles. It requires ftell and fseek though. If I remove the two references to ftell and fseek, everything compiles ok. It also fits in the ATxmega128's flash, just barely. I moved the heap and variables to the external SDRAM. What remains to be seen is if 32MHz XMEGA can decode in real time. I'm hoping to stream the ogg file into the xmega over the USB comm port and hear the decoded audio on the xplain's little speaker. I may have to upgrade to a UC3 xplain instead.

I like cats, too. Let's exchange recipes.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Exactly what filing system were you planning to use them with? AVR(8)s do not have any filing system device and that's why AVR-LibC does not have support. It does, however have the special FDEV_SETUP_STREAM mechanism to allow you to create streaming functions but theses would be to character, not  block devices.

 

When you add a filing system to AVR (FatFS from E L Chan being the popular one) he provides :

 

http://elm-chan.org/fsw/ff/en/ls...

and

http://elm-chan.org/fsw/ff/en/te...

 

(and surely your code uses more than just seek and tell? Does it not use open, close and read? How else does it actually read the Ogg data?)

 

EDIT: Oh I see they use stdin as a pipe so you presumably use:

ogg_example < file.ogg

That's not going to work in AVR as there is no command shell to open file.ogg and (<) pipe it into app.

Last Edited: Thu. Oct 9, 2014 - 03:49 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I was configuring stdio with the USART as the stdin and stdout. I have not dug deeply into the Tremor code enough to see how the stream is manipulated after that though.

I like cats, too. Let's exchange recipes.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ivorbis_example.c does this:

  if(ov_open(stdin, &vf, NULL, 0) < 0) {

then vorbisfile.c has this:

int ov_open_callbacks(void *f,OggVorbis_File *vf,char *initial,long ibytes,
    ov_callbacks callbacks){
  int ret=_ov_open1(f,vf,initial,ibytes,callbacks);
  if(ret)return ret;
  return _ov_open2(vf);
}

int ov_open(FILE *f,OggVorbis_File *vf,char *initial,long ibytes){
  ov_callbacks callbacks = {
    (size_t (*)(void *, size_t, size_t, void *))  fread,
    (int (*)(void *, ogg_int64_t, int))              _fseek64_wrap,
    (int (*)(void *))                             fclose,
    (long (*)(void *))                            ftell
  };

  return ov_open_callbacks((void *)f, vf, initial, ibytes, callbacks);
}

and

static int _ov_open1(void *f,OggVorbis_File *vf,char *initial,
		     long ibytes, ov_callbacks callbacks){
  int offsettest=(f?callbacks.seek_func(f,0,SEEK_CUR):-1);
  int ret;

  memset(vf,0,sizeof(*vf));

  /* Tremor assumes in multiple places that right shift of a signed
     integer is an arithmetic shift */
  if( (-1>>1) != -1) return OV_EIMPL;

  vf->datasource=f;
  vf->callbacks = callbacks;

  /* init the framing state */
  vf->oy=ogg_sync_create();

  /* perhaps some data was previously read into a buffer for testing
     against other stream types.  Allow initialization from this
     previously read data (as we may be reading from a non-seekable
     stream) */
  if(initial){
    unsigned char *buffer=ogg_sync_bufferin(vf->oy,ibytes);
    memcpy(buffer,initial,ibytes);
    ogg_sync_wrote(vf->oy,ibytes);
  }

  /* can we seek? Stevens suggests the seek test was portable */
  if(offsettest!=-1)vf->seekable=1;

  /* No seeking yet; Set up a 'single' (current) logical bitstream
     entry for partial open */
  vf->links=1;
  vf->os=ogg_stream_create(-1); /* fill in the serialno later */

  /* Try to fetch the headers, maintaining all the storage */
  if((ret=_fetch_headers(vf,&vf->vi,&vf->vc,&vf->current_serialno,NULL))<0){
    vf->datasource=NULL;
    ov_clear(vf);
  }else if(vf->ready_state < PARTOPEN)
    vf->ready_state=PARTOPEN;
  return ret;
}

static int _ov_open2(OggVorbis_File *vf){
  if(vf->ready_state < OPENED)
    vf->ready_state=OPENED;
  if(vf->seekable){
    int ret=_open_seekable2(vf);
    if(ret){
      vf->datasource=NULL;
      ov_clear(vf);
    }
    return ret;
  }
  return 0;
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I just got everything setup in Visual Studio and compiled on Windows, and it works. I'm trying to see how I can remove the seek calls without breaking everything.

I like cats, too. Let's exchange recipes.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I see what I'm doing wrong now. Since I'm using character IO instead of block IO, I need to use the lower-level libvorbis calls and implement a memory buffer to create the packets necessary to feed to the vorbis DSP routines.

I like cats, too. Let's exchange recipes.