From beakerboy99 at yahoo.com  Tue Feb  8 22:35:34 2005
From: beakerboy99 at yahoo.com (Kevin Nowaczyk)
Date: Tue, 8 Feb 2005 19:35:34 -0800 (PST)
Subject: Writing decoded audio to stdout
Message-ID: <20050209033534.37638.qmail@web60707.mail.yahoo.com>

I have a working application which decodes ogg and mp3
files and plays them.  I'd like to add the option of
writing the audio to stdout in other to link in other
software through a pipe.  

I can succesfully use:
Sound_Sample* sample = Sound_NewSampleFromFile
(p.string ().c_str (), NULL, decode_buffersize); 

What do I need to do to this sample to make it work
with the Sound_Decode() function.  Here's what I have
currently.  It's a cut-up version of the working SDL
implementation.  I took the code from the callback and
moved it into the play funtion.  It looks like I may
need to know how to cut my sample up into smaller
pieces like SDL_AudioSpec userdata.  ANy help would be
greatly appreciated.

void AudioPlayer::play (fs::path p)
{
    Uint32 audio_buffersize = DEFAULT_AUDIOBUF;
    Uint32 decode_buffersize = DEFAULT_DECODEBUF;

    Sound_Sample *sample;

    sample = Sound_NewSampleFromFile (p.string
().c_str (), NULL, decode_buffersize);

    if (!sample)
      {
        fprintf(stderr, "Couldn't load \"%s\"!\n"
                        "  reason: [%s].\n",
p.string().c_str(), Sound_GetError());
        return;
      }

    if (sample->flags & SOUND_SAMPLEFLAG_ERROR)
      {
        fprintf(stderr, "Error in decoding sound
file!\n"
                        "  reason: [%s].\n",
Sound_GetError());
      }

    int bw = 0;
    Uint8 stream1[decode_buffersize];
    while (bw < decode_buffersize)
      {
        int cpysize;
        if (!read_more_data(sample))
          {
            memset(stream1 + bw, '\0',
decode_buffersize - bw);
            done_flag = 1;
            return;
          }
        cpysize = decode_buffersize - bw;
        if (cpysize > deco1G1Gded_bytes)
            cpysize = decoded_bytes;

        if (cpysize > 0)
          {
            memcpy(stream1 + bw , decoded_ptr,
cpysize);
            bw += cpysize;
            decoded_ptr += cpysize;
            decoded_bytes -= cpysize;
          }
      }
i//    printf ("%s", stream1);
    std::cout << stream1;
    Sound_FreeSample(sample);
}



		
__________________________________ 
Do you Yahoo!? 
All your favorites on one personal page ? Try My Yahoo!
http://my.yahoo.com 


From icculus at clutteredmind.org  Wed Feb  9 16:26:57 2005
From: icculus at clutteredmind.org (Ryan C. Gordon)
Date: Wed, 09 Feb 2005 16:26:57 -0500
Subject: [sdlsound] Writing decoded audio to stdout
In-Reply-To: <20050209033534.37638.qmail@web60707.mail.yahoo.com>
References: <20050209033534.37638.qmail@web60707.mail.yahoo.com>
Message-ID: <420A8021.5040108@clutteredmind.org>


>     if (sample->flags & SOUND_SAMPLEFLAG_ERROR)

You don't have to check ERROR here...you won't get a new Sound_Sample 
with an error state...this flag should be checked after Sound_Decode(), 
if you didn't get as many bytes as you requested (in which case it's 
either an ERROR or an EOF).

>     Uint8 stream1[decode_buffersize];
>     while (bw < decode_buffersize)

This is a bug. You decode enough to fill a single buffer and then quit.

This looks like you cut-and-pasted from playsound.c, which is probably 
over-complicated for what you want to do...besides all the extra crap it 
does, it also has to account for having to feed the audio device 
incrementally over time from a buffer that might have more or less data 
available...when going to disk or a pipe, you can just dump as fast as 
you can without tapdancing.

  const char *fname = p.string().c_str();
  Sound_Sample * sample = Sound_NewSampleFromFile (fname, NULL, 1024*64);
  if (!sample) {
      cerr << "Error opening " << fname << ": " << Sound_GetError();
      return;
  }

  do {
      Uint32 br = Sound_Decode(sample);
      if (br > 0)  // write this block of decoded data to stdout.
          cout.write((const char *) sample->buffer, sample->buffer_size);

      if (sample->flags & SOUND_SAMPLEFLAG_ERROR) {
          cerr << "Error decoding " << fname << ": " << Sound_GetError();
          break;
      }
  } while (sound->flags & SOUND_SAMPLEFLAG_EOF);

  Sound_FreeSample(sample);

--ryan.



From beakerboy99 at yahoo.com  Tue Feb 15 22:00:14 2005
From: beakerboy99 at yahoo.com (Kevin Nowaczyk)
Date: Tue, 15 Feb 2005 19:00:14 -0800 (PST)
Subject: [sdlsound] Writing decoded audio to stdout
In-Reply-To: <420A8021.5040108@clutteredmind.org>
Message-ID: <20050216030015.93623.qmail@web60703.mail.yahoo.com>

Ryan,
Thanks for the code! I transfered it in and it kind of
works. There are things which seem to not be working
as I'd expect.  When I redirect stdout to the audio
device I hear static.  The other thing is if I
redirect stdout to a file, the file is always the size
of one buffer.  It seems like the the audio sample is
never refreshed.  I've tried to get some help from the
Doxygen API refernece on the website, but I'm new to
the world of SDL and had a hard time following what
needed to be done.  

I've included a small c++ file with your code.  If you
compile and run it with an audiofile name as a
commandline parameter and redirect stdout to either
audio or a file, you should see what I'm talking
about.

#include <SDL_sound.h>
#include <iostream>

class AudioPlayer
{
  public:
    AudioPlayer()
      {
        Sound_Init();
      }

    ~AudioPlayer()
      {
        Sound_Quit();
      }

    void play (char*);
};

void AudioPlayer::play (char* fname)
  {
    Sound_Sample* sample = Sound_NewSampleFromFile
(fname, NULL, 1024*64);
    if (!sample) 
      {
        std::cerr << "Error opening " << fname << ": "
<< Sound_GetError () << std::endl; 
        return;
      }
    do 
      {
        Uint32 br = Sound_Decode(sample);
        if (br > 0)  // write this block of decoded
data to stdout.
          std::cout.write((const char *)
sample->buffer, sample->buffer_size);
        if (sample->flags & SOUND_SAMPLEFLAG_ERROR) 
          {
            std::cerr << "Error decoding " << fname <<
": " << Sound_GetError() << std::endl;
            break;
          }
      } while (sample->flags & SOUND_SAMPLEFLAG_EOF);
    
    Sound_FreeSample(sample);
  }

main(int argc,char** argv)
{
  if (argc == 2)
    {
      char* filename = argv[1];
      AudioPlayer player;
      player.play(filename);

    }
  else
   {
     std::cout << "please provide a filename" <<
std::endl;
   }

}


Thanks for any help you can give me,
Kevin Nowaczyk

--- "Ryan C. Gordon" <icculus at clutteredmind.org>
wrote:

> 
> >     if (sample->flags & SOUND_SAMPLEFLAG_ERROR)
> 
> You don't have to check ERROR here...you won't get a
> new Sound_Sample 
> with an error state...this flag should be checked
> after Sound_Decode(), 
> if you didn't get as many bytes as you requested (in
> which case it's 
> either an ERROR or an EOF).
> 
> >     Uint8 stream1[decode_buffersize];
> >     while (bw < decode_buffersize)
> 
> This is a bug. You decode enough to fill a single
> buffer and then quit.
> 
> This looks like you cut-and-pasted from playsound.c,
> which is probably 
> over-complicated for what you want to do...besides
> all the extra crap it 
> does, it also has to account for having to feed the
> audio device 
> incrementally over time from a buffer that might
> have more or less data 
> available...when going to disk or a pipe, you can
> just dump as fast as 
> you can without tapdancing.
> 
>   const char *fname = p.string().c_str();
>   Sound_Sample * sample = Sound_NewSampleFromFile
> (fname, NULL, 1024*64);
>   if (!sample) {
>       cerr << "Error opening " << fname << ": " <<
> Sound_GetError();
>       return;
>   }
> 
>   do {
>       Uint32 br = Sound_Decode(sample);
>       if (br > 0)  // write this block of decoded
> data to stdout.
>           cout.write((const char *) sample->buffer,
> sample->buffer_size);
> 
>       if (sample->flags & SOUND_SAMPLEFLAG_ERROR) {
>           cerr << "Error decoding " << fname << ": "
> << Sound_GetError();
>           break;
>       }
>   } while (sound->flags & SOUND_SAMPLEFLAG_EOF);
> 
>   Sound_FreeSample(sample);
> 
> --ryan.
> 
> 


=====
Manage your PEZ collection online.  Visit PezBase at http://pezbase.beakerboy.com


		
__________________________________ 
Do you Yahoo!? 
Yahoo! Mail - Easier than ever with enhanced search. Learn more.
http://info.mail.yahoo.com/mail_250


From icculus at clutteredmind.org  Wed Feb 16 03:59:11 2005
From: icculus at clutteredmind.org (Ryan C. Gordon)
Date: Wed, 16 Feb 2005 03:59:11 -0500
Subject: [sdlsound] Writing decoded audio to stdout
In-Reply-To: <20050216030015.93623.qmail@web60703.mail.yahoo.com>
References: <20050216030015.93623.qmail@web60703.mail.yahoo.com>
Message-ID: <42130B5F.8010406@clutteredmind.org>


>>  } while (sound->flags & SOUND_SAMPLEFLAG_EOF);

Whoops. We're writing one block and quitting...I think that was my bug.

} while ((sound->flags & SOUND_SAMPLEFLAG_EOF) == 0);

Also, you generally can't just redirect to /dev/dsp (or whatever); if 
the audio data's not the same format it expects, it'll give you static 
since it's trying to play the binary data as if it's some other format, 
which never works out well.

--ryan.



From beakerboy99 at yahoo.com  Wed Feb 16 08:31:46 2005
From: beakerboy99 at yahoo.com (Kevin Nowaczyk)
Date: Wed, 16 Feb 2005 05:31:46 -0800 (PST)
Subject: [sdlsound] Writing decoded audio to stdout
In-Reply-To: <42130B5F.8010406@clutteredmind.org>
Message-ID: <20050216133148.77283.qmail@web60707.mail.yahoo.com>

Thanks for the help!  It looks like it working now. 
My brother, who is quite the linux guru, had me
convinced that the decode function would be returning
raw audio like a .au file and that redirecting this to
the audio device will play the file.  I'll have to
tell him that this isn't the case.

Now I get to see if I can link this up with icecast :)

Kevin Nowaczyk

--- "Ryan C. Gordon" <icculus at clutteredmind.org>
wrote:

> 
> >>  } while (sound->flags & SOUND_SAMPLEFLAG_EOF);
> 
> Whoops. We're writing one block and quitting...I
> think that was my bug.
> 
> } while ((sound->flags & SOUND_SAMPLEFLAG_EOF) ==
> 0);
> 
> Also, you generally can't just redirect to /dev/dsp
> (or whatever); if 
> the audio data's not the same format it expects,
> it'll give you static 
> since it's trying to play the binary data as if it's
> some other format, 
> which never works out well.
> 
> --ryan.
> 
> 


=====
Manage your PEZ collection online.  Visit PezBase at http://pezbase.beakerboy.com

__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 


