EscII Skrevet 18. januar 2010 Del Skrevet 18. januar 2010 Hei. Jeg skal lage et program som spiller av en tone når jeg trykker på en tast. Om jeg må lage lydfilen på forhånd (som mp3, wav eller lignende, for så å få programmet til å spille den av) eller om programmet selv lager tonen (trenger ikke være mer enn en sinustone), går egentlig for det samme, selvom det siste er å foretrekke. Det jeg lurer på er hvordan man i det hele tatt kan få et program, skrevet i C, til å spille av lyd. Lenke til kommentar
GeirGrusom Skrevet 18. januar 2010 Del Skrevet 18. januar 2010 Anbefaler OpenAL. Enkelt og kraftig. Lenke til kommentar
TheMaister Skrevet 18. januar 2010 Del Skrevet 18. januar 2010 (endret) For å få programmert noe lyd i C er du nødt til å jobbe opp mot eksterne API-er. Og det finnes mange av dem. Kommer an på hvilket OS du sitter på så klart. Geir: Er ikke OpenAL et ganske tungt API å jobbe opp mot? Trenger absolutt ikke noe som OpenAL for å generere en sinus-tone. Hvis du sitter på Linux kan du prøve denne koden. Den spiller av A-dur og A-moll skalaen :3 Simpel OSS-kode følger under. Prinsippet for å spille av lyd er stort sett det samme, men du vil kanskje benytte deg av andre funksjoner. #include <sys/soundcard.h> #include <math.h> #include <sys/ioctl.h> #include <fcntl.h> #include <stdlib.h> void generate_sine(int fd, char *buffer, int size, int samplerate, int halftone) { int count; for( count = 0; count < size; count++ ) { // Generer en sinusfunksjon med frekvens avhenging av halvtone buffer[count] = (int) 0xFF/2*sin(2*3.1415*440*powf(2, (float)halftone/12)*(float)count/(float)samplerate); } write( fd, buffer, size ); } int main() { int fd = open("/dev/dsp", O_WRONLY, 0); // 8-bit int format = AFMT_S8; ioctl( fd, SNDCTL_DSP_SETFMT, &format ); // Mono int stereo = 0; ioctl( fd, SNDCTL_DSP_STEREO, &stereo ); // 44100 Hz samplerate int samplerate = 44100; ioctl( fd, SNDCTL_DSP_SPEED, &samplerate ); // 0.25s med lyd char *buffer = malloc ( samplerate/4 ); // Dur-skala :3 int halftone_major[8] = {0, 2, 4, 5, 7, 9, 11, 12}; int halftone_minor[8] = {0, 2, 3, 5, 7, 8, 10, 12}; int count; for ( count = 0; count < 8; count++ ) { generate_sine(fd, buffer, samplerate/4, samplerate, halftone_major[count]); } for ( count = 0; count < 8; count++ ) { generate_sine(fd, buffer, samplerate/4, samplerate, halftone_minor[count]); } close( fd ); return 0; } Endret 18. januar 2010 av TheMaister Lenke til kommentar
GeirGrusom Skrevet 19. januar 2010 Del Skrevet 19. januar 2010 Det er egentlig ganske simpelt. OpenAL er cross-platform også ^^ Lenke til kommentar
EscII Skrevet 19. januar 2010 Forfatter Del Skrevet 19. januar 2010 Takk for svar TheMaister: Jeg sitter på Linux, men jeg får ikke koden til å fungere. På linjen char *buffer = malloc ( samplerate/4 ); får jeg feilen "invalid conversion from 'void*' to 'char*'". Noen forslag? GeirGrusom: Hvordan er det å lære seg å bruke openAL. Jeg har litt knapt med tid. Takk for all hjelp! Lenke til kommentar
GeirGrusom Skrevet 19. januar 2010 Del Skrevet 19. januar 2010 Du bruker C++ tydeligvis. Cast til char* char *buffer = (char*)malloc ( samplerate/4 ); Dårlig tid er en utviklers verste fiende. Lenke til kommentar
EscII Skrevet 19. januar 2010 Forfatter Del Skrevet 19. januar 2010 Yes! Der funka det Tusen takk! Tror ikke jeg bruker C++. Filen heter i hvert fall *.c. Lenke til kommentar
Bytex Skrevet 19. januar 2010 Del Skrevet 19. januar 2010 Kan man ikke bruke av MIDI-lydene på lydkortet også? Istedet for å gå via andre API'er..alle lydkort har jo innebygde midi-lyder. Lenke til kommentar
GeirGrusom Skrevet 19. januar 2010 Del Skrevet 19. januar 2010 Yes! Der funka det Tusen takk! Tror ikke jeg bruker C++. Filen heter i hvert fall *.c. Det at filen slutter på .c betyr bare at filen slutter på .c Det er compileren du bruker som bestemmer hvilket språk som ligger i filen. GCC skal prøve å gjette på compiler etter filtype, men dersom du tvinger frem bruk av C++ (for eksempel ved å bruke g++) så spiller det ingen rolle hva extension til fila er. Lenke til kommentar
TheMaister Skrevet 19. januar 2010 Del Skrevet 19. januar 2010 Det er egentlig ganske simpelt. OpenAL er cross-platform også ^^ Kunne du ha vist et enkelt eksempel som likner på det ovenfor? Vil sammenlikne det kontra PortAudio som multiplatform. Lenke til kommentar
GeirGrusom Skrevet 19. januar 2010 Del Skrevet 19. januar 2010 (endret) Noe lignende i OpenAL: #include <AL.H> #include <ALC.H> #include <malloc.h> #include <stdlib.h> #include <stdio.h> #include <math.h> #define PI 3.1415 void CreateSineWave(short* buffer, int samples, int sample_rate, double frequency, double amplitude) { double sample_increment = (PI * 2) / sample_rate; double period = 0; amplitude = amplitude > 1 ? 1 : (amplitude < 0 ? 0 : amplitude); for(int i = 0; i < samples; i++) { double sinp = sin(period += sample_increment * frequency) * amplitude; short val = (short)(sinp * 32767); buffer[i] = val; } } int main(int argc, char** argv) { ALCdevice *device = alcOpenDevice(NULL); ALCcontext* ctx = NULL; if(device) { ctx = alcCreateContext(device, NULL); alcMakeContextCurrent(ctx); } else { printf("Failed to open audio device."); return 1; } const int sample_rate = 44100; const int samples = 4 * sample_rate; short sinewave[samples]; // Lag et fire sekunder langt buffer CreateSineWave(sinewave, samples, sample_rate, 500, .1); unsigned int buffer = 0; unsigned int source = 0; alGenBuffers(1, &buffer); alGenSources(1, &source); alBufferData(buffer, AL_FORMAT_MONO16, sinewave, sizeof(sinewave), sample_rate); alSourcei(source, AL_BUFFER, buffer); alSourcePlay(source); getchar(); alcDestroyContext(ctx); return 0; } Så det skal ikke så mye til for å gjøre enkle ting. Det er dog ingen innebygget støtte for noen lydformater (på samme måte som det ikke er noen innebygget støtte for bildeformater i OpenGL) men ALC inneholder en funksjon for å laste .WAV filer. Utover det, er det ingen kunst å bruke libvorbisfile for å spille av Ogg Vorbis filer. Det er kanskje mulig å bruke DirectShow på Windows også, men jeg har ikke vært borti DirectShow i C++. edit: MP3 og Ogg Vorbis er støttet gjennom extensions. Endret 21. januar 2010 av GeirGrusom Lenke til kommentar
Anbefalte innlegg
Opprett en konto eller logg inn for å kommentere
Du må være et medlem for å kunne skrive en kommentar
Opprett konto
Det er enkelt å melde seg inn for å starte en ny konto!
Start en kontoLogg inn
Har du allerede en konto? Logg inn her.
Logg inn nå