[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: debian, SDL1.2 & audio



> А что за карточка?

"Чудо" под названием VIA vt82c686.

> А если mp3 через xmms играть - оно с нормальной скоростью получается?
> А через mplayer?

Без проблем. И то и другое.
Да в общем-то и все прочие, даже нативные виндовые гамесы под wine/winex.

> Просто на карточке может стоять другой битрейт (например 48hz)..

Да, на 44100 она ругается.
Пробовал ему "подсунуть" 48kHz - эффект тот же, хотя через obtained audio 
SDL_AudioSpec говорит, что вот 48kHz поддерживает.

Кстати, "о птичках" - почему-то в SDL_Init/SDL_InitSubsystem джойстик надо 
"поднимать" только вместе с видео, иначе и не рекомендуют да и не работать 
хотит .. это бага или фича ?

> Давай код в студию -- посмотрим.

attached.
За форматирование, pls, сильно не бить - это vc6 "постарался". :(

WBR, Burzumie.
#ifdef WIN32
#include <windows.h>
#else
#include <unistd.h>
#include <signal.h>
#endif

#include <string.h>
#include <stdlib.h>
#include <vorbis/codec.h>
#include <vorbis/vorbisfile.h>
#include <SDL/SDL.h>

#ifdef WIN32
// may be dangerous (!). will be removed
#define snprintf _snprintf
#pragma comment(lib, "SDL.lib")
//#pragma comment(lib, "vorbisfile_d.lib")
// static linking under win32
#pragma comment(lib, "ogg_static.lib")
#pragma comment(lib, "vorbis_static.lib")
#pragma comment(lib, "vorbisfile_static.lib")
#endif

#include <iostream>
using namespace std;


struct sStatic_init
{
    Uint32 SDL_init_flags;
	
    sStatic_init()
    {
		SDL_init_flags = SDL_INIT_AUDIO;
		
		if (SDL_Init(SDL_init_flags) < 0)
		{
			cerr << "Couldn't initialize SDL: " << SDL_GetError() << endl;
			exit(EXIT_FAILURE);
		}
    }
	
    ~sStatic_init()
    {
		SDL_QuitSubSystem(SDL_init_flags);
    }
} static_init; 


const char *filename = "1.ogg";

OggVorbis_File vf;
int current_section;
char pcmout[4096];

char buffer[65535];

static bool done = false;

int chunk_num = 0;
unsigned int data_carried = 0;

void my_audio_callback(void *userdata, Uint8 *stream, int len)
{
	// for messages
	char s[1024];

	int filled = 0;

	if(data_carried > 0)
	{
		memcpy(stream, buffer, data_carried);
		filled = data_carried;
		data_carried = 0;
	}

	do
    {
		// decode next chunk
		long ret = ov_read(&vf, pcmout, sizeof(pcmout), 0, 2, 1, &current_section);
		if (ret == 0)
		{
			// EOF
			cerr << "EOF reached" << endl;
			SDL_PauseAudio(1);
			done = true;
			return;
		}
		else
			if (ret < 0)
			{
			/* error in the stream.  Not a problem, just reporting it in
				case we (the app) cares.  In this case, we don't. */
				cerr << "error in stream" << endl;
				exit(1);
			}
			else
			{
			/* we don't bother dealing with sample rate changes, etc, but you'll have to */

				int rest;
				// will be end of buffer reached ?
				if((filled + ret) > len)
				{
					rest = len - filled;

					data_carried = (filled + ret) - len;	// must be always > 0
					if(data_carried > sizeof(buffer))
					{
						snprintf(s, sizeof(s), "data overflow: carried %i bytes in chunk %i, only %i reserved", data_carried, chunk_num, sizeof(buffer));
#ifdef WIN32
						MessageBox(0, s, "error", NULL);
#else
						cerr << s << endl;
#endif
						exit(1);
					}
					else
					{
						memcpy(buffer, pcmout+(ret - data_carried), data_carried);
					}
				}
				else
				{
					rest = ret;
				}

				memcpy(stream + filled, (Uint8 *)(pcmout), rest);
				filled += ret;
			}
    } while(filled < len);	// must fill all 'stream' buffer

	++chunk_num;
}

void sighandler(int sig)
{
    done = true;
}

/*
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
*/
int main()
{
    SDL_AudioSpec *desired, *obtained;
    SDL_AudioSpec *hardware_spec;
	
    desired = new SDL_AudioSpec;
    obtained = new SDL_AudioSpec;
	
    desired->freq=48000;
    desired->format=AUDIO_S16LSB;
    desired->channels=2;
    desired->samples=4096;
	
    desired->callback=my_audio_callback;
	
    desired->userdata=NULL;

    char s[1024];
	
    // open the audio device
    int r = SDL_OpenAudio(desired, obtained);
    if ( r < 0 )
    {
		snprintf(s, sizeof(s), "Couldn't open audio: %s", SDL_GetError());
#ifdef WIN32
		MessageBox(0, s, "error", NULL);
#else
		cerr << s << endl;
#endif
		return 1;
    }
	
    // desired spec is no longer needed
//    delete desired;
	
    hardware_spec = obtained;

    FILE *f = fopen(filename, "rb");
    if(f == NULL)
    {
		snprintf(s, sizeof(s), "Error opening input file: %s", strerror(errno));
#ifdef WIN32
		MessageBox(0, s, "error", NULL);
#else
		cerr << s << endl;
#endif

		return 1;
    }

    if(ov_open(f, &vf, NULL, 0) < 0)
    {
		snprintf(s, sizeof(s), "Input file does not appear to be an Ogg bitstream.");
#ifdef WIN32
		MessageBox(0, s, "error", NULL);
#else
		cerr << s << endl;
#endif
		return 1;
    }

#ifndef WIN32
    signal(SIGHUP, sighandler);
    signal(SIGINT, sighandler);
    signal(SIGQUIT, sighandler);
    signal(SIGTERM, sighandler);

     signal(SIGTTOU, SIG_IGN);
#endif

    char audio_driver_name[32];
	snprintf(s, sizeof(s), "Using audio driver: %s", SDL_AudioDriverName(audio_driver_name, 32));
#ifdef WIN32
	MessageBox(0, s, "info", NULL);
#else
struct audio_hw_fmt
{
    char *fmt_name;
    Uint16 fmt;
} audio_hw_fmt_tbl[] =
{
    { "AUDIO_U8", 0x0008 },
    { "AUDIO_S8", 0x8008 },
    { "AUDIO_U16LSB", 0x0010 },
    { "AUDIO_S16LSB", 0x8010 },
    { "AUDIO_U16MSB", 0x1010 },
    { "AUDIO_S16MSB", 0x9010 }
};
    cout << s << endl;
    cout << "Obtained hardware SDL_AudioSpec are: " << endl;
    cout << "  frequency: " << int(hardware_spec->freq) << endl;
    cout << "  format: " << int(hardware_spec->format);
    char *sp = NULL;
    for(unsigned int i = 0; i < sizeof(audio_hw_fmt_tbl); ++i)
    {
	if(audio_hw_fmt_tbl[i].fmt == hardware_spec->format)
	{
	    sp = audio_hw_fmt_tbl[i].fmt_name;
	    break;
	}
    }
    cout << " (" << (sp != NULL ? sp : "unknown") << ")" << endl;
    cout << "  channels: " << int(hardware_spec->channels) << endl;
    cout << "  samples: " << int(hardware_spec->samples) << endl;
#endif

	
    // Start playing
    SDL_PauseAudio(0);
	
    while ( (done == false) && (SDL_GetAudioStatus() == SDL_AUDIO_PLAYING) )
    {
	SDL_Delay(1000);
    }
    SDL_PauseAudio(1);
	
    // cleanup
    SDL_CloseAudio();
    ov_clear(&vf);
	
    delete obtained;

	snprintf(s, sizeof(s), "done");
#ifdef WIN32
	MessageBox(0, s, "info", NULL);
#else
    cout << s << endl;
#endif

    return 0;
}

Reply to: