Thread: C program to play a sound

  1. #1
    Registered User
    Join Date
    Aug 2008
    Posts
    3

    C program to play a sound

    Hi to everyone... recently changed to linux and i need some help with this new adventure...
    i changed to Linux because everybody told me that is the best OS to make my own programs and stuffs... but so far it doesn't seems to be different that Windows (even more complicated).


    i need a code to play a sound (.mp3 .wav, any format) written in C (is the only language i know)
    hopefully as simple as

    init_device();
    play("sample.mp3");
    stop("sample.mp3);

    or something like that...

    it's prudent to stay in C/C++ ?... or should i change to another language...such as Java?

    thanks a lot !!!

  2. #2
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    I'm new to C but I've been using linux for years -- I would NEVER recommend it to anyone, however, because it has such a ridiculous learning curve attached. But once you're comfortable windows looks like chintzy junk...

    Anyway I presume you want play to be a function from some library. I don't know if such a thing exists for linux or windows, but you could look around. Linux C uses GNU glibc, if you haven't yet, see the official docs:
    www.delorie.com/gnu/docs/glibc/libc_toc.html
    Which includes an index to all standard functions.
    Otherwise try execvp("mpg123 file.mp3", NULL);

    ps. I hate to mention perl...
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  3. #3
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    I'm pretty sure that the example you gave will try to execute a program called "mpg123 file.mp3", instead of executing a program called "mpg123" and passing "file.mp3" as a parameter.

    A simple-ish way to do this is to use
    Code:
    system("program file.mp3");
    where system() is in <stdlib.h> and program is the program you wish to use to open the file. I have no idea what mp3 player(s) you might have; you'll want to check. If you're using KDE, you might start with
    Code:
    system("konqueror file.mp3");
    BTW -- I'd recommend Linux to someone who is willing to learn a little bit. If you don't like it, you can always switch back.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  4. #4
    Registered User
    Join Date
    Aug 2008
    Posts
    3
    hi, thanks to those who answered...

    i wasn't vary clear of what i wanned to accomplish...
    what i need is a library or function that let me play a sound IN the program, not calling another program such as totem or conqueror...
    i believe that Java is the answer... i couldn0t find anything to so such thing (in C)...

  5. #5
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Well, you'll have to use an external library of some sort. The SDL along with SMPEG, for example. (There are probably easier ways, but I don't know of them.)

    [edit] Of course, there are online tutorials and such so you could probably find code almost already-written for you.
    http://www.gamedev.net/community/for...opic_id=348801
    http://listas.apesol.org/pipermail/s...er/059216.html
    [/edit]

    Either way, it's going to be quite difficult to do this. If you know how to do it in Java, by all means try it. Just make sure your Linux system can run Java programs.
    Last edited by dwks; 08-05-2008 at 06:50 PM.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  6. #6
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300

    Lightbulb

    DWK was right about my invocation of "execvp" being wrong -- hopefully i'm about to correct myself.

    If your problem with using "system" or "exec" is that you can't stop playback after it's started, then I have your solution (I once made a perl/Tk mp3 app where this figured in). Linux uses process id's ("pid"s) to track all running processes (see a list with "ps"), and you can signal the mp3 playing process to do different things with it's pid.

    If you use a simple console based app like mpg123, you can call it without any pop-up windows popping up, etc -- it just plays the file. Then get the pid and kill it when you want. In perl "system" forks a process automatically and returns you the new pid (easy). In C, running a separate program with "system" and "exec" does NOT give you a new pid -- so if you kill the "mpg123" process you will kill your entire program. So you have to fork a process (=what I learned about C today).

    Anyway, the following code will play a song until you hit ENTER, then it kills mpg123 (stopping the playback) and leaves a message.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h> // for execlp
    
    int main () {
            pid_t x;      // a special kind of int
            char kil[20] = "kill -s 9 ";
    
            x = fork();   /* now there's actually two "x"s:
    if fork succeeds, "x" to the CHILD PROCESS is the return value of fork (0)
    and "x" to the PARENT PROCESS is the actual system pid of the child process.*/
            
            if (x < 0) {  // just in case fork fails 
                    puts("fork failure");
                    exit(-1);
            }   
            else if (x == 0) { // therefore this block will be the child process 
                    execlp("mpg123", "mpg123", "-q", "/songs/bertha.mp3", 0); 
            }                   // see GNU docs, "system" also works                
            else {  printf("from parent: mpg123 is pid %d\nENTER to quit\n", x);
                    sprintf(kil,"%s%d",kil,x);
                    getchar();  // wait for user input
                    system(kil);
                    printf("All ");
            }       /* witness that the "else if" and "else" blocks are both executed here in parallel. The "else" 
       (parent) block is continuous with the rest of the program (since the PARENT PROCESS is actually
       the program itself) so... */
            printf("done.\n");
            exit(0);
    }
    Get it? Anyway, that might be all you need.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  7. #7
    Registered User
    Join Date
    Aug 2008
    Posts
    3
    Thanks a lot MK27 !!!... that is exactly what i was searching for...
    one thing though... there is any way to do this without the fork command?...
    like getting the ID (pid number) of the execlp and the kill it...
    because of what i understand of the code... the child is the one that send the play command, and the parent stop it... i'm right?...

    thanks a lot...

  8. #8
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300

    Red face

    I'm new to C, but I don't think you can do it without fork for a couple of reasons (mostly the first one):

    (1) without fork, the pid of your program and the pid of the system command (mpg123) will be the same, meaning if you kill one, you kill everything.

    (2) without fork, mpg123's console output (even if there is none, which is what the "-q" switch does) seems to occupy the terminal, meaning without a GUI there is no way to control the program while mpg123 runs. You could "background" the command (add an "&" to the end, eg. mpg123 -q song.mp3 & -- this only works via "system"), but you still won't get a new pid. Likewise, you could create a pipe and funnel off mpg123's stdout...this is even more complicated and doesn't work because of (1), again.

    Anyway, good luck, fork seems like a useful thing to learn, which is what got me into this i guess. (Maybe some pro will come along and wisely contradict).

    ps. yes, the child sends the command, the parent (which is really the program itself) kills it.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  9. #9
    Registered User valaris's Avatar
    Join Date
    Jun 2008
    Location
    RING 0
    Posts
    507
    You could probably use the kill() function instead of invoking an extra call to system() I believe.

  10. #10
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    "You could probably use the kill() function instead of invoking an extra call to system() I believe."

    Yes, next time i will, promise.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  11. #11
    Registered User
    Join Date
    Aug 2008
    Location
    Gastonia, NC
    Posts
    2
    One of the great things about C/C++ is you can use library's to add functions.
    As one has already posted, SDL or FMOD library can be called from a C program.
    Without using a shell and having to kill a process.

    With these library's, not only can you play WAV, MP3, etc. but have other controls over the sound, like volume, tone, speed. Can start and stop the sound at any point durring playback.

    I used both of the above libraries with C.

    Look at this SDL example http://www.libsdl.org/intro.en/usingsound.html
    Last edited by nexusone; 08-13-2008 at 07:35 PM.

  12. #12
    Registered User
    Join Date
    Dec 2006
    Posts
    136
    Quote Originally Posted by MK27 View Post
    DWK was right about my invocation of "execvp" being wrong -- hopefully i'm about to correct myself.

    If your problem with using "system" or "exec" is that you can't stop playback after it's started, then I have your solution (I once made a perl/Tk mp3 app where this figured in). Linux uses process id's ("pid"s) to track all running processes (see a list with "ps"), and you can signal the mp3 playing process to do different things with it's pid.

    If you use a simple console based app like mpg123, you can call it without any pop-up windows popping up, etc -- it just plays the file. Then get the pid and kill it when you want. In perl "system" forks a process automatically and returns you the new pid (easy). In C, running a separate program with "system" and "exec" does NOT give you a new pid -- so if you kill the "mpg123" process you will kill your entire program. So you have to fork a process (=what I learned about C today).

    Anyway, the following code will play a song until you hit ENTER, then it kills mpg123 (stopping the playback) and leaves a message.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h> // for execlp
    
    int main () {
            pid_t x;      // a special kind of int
            char kil[20] = "kill -s 9 ";
    
            x = fork();   /* now there's actually two "x"s:
    if fork succeeds, "x" to the CHILD PROCESS is the return value of fork (0)
    and "x" to the PARENT PROCESS is the actual system pid of the child process.*/
            
            if (x < 0) {  // just in case fork fails 
                    puts("fork failure");
                    exit(-1);
            }   
            else if (x == 0) { // therefore this block will be the child process 
                    execlp("mpg123", "mpg123", "-q", "/songs/bertha.mp3", 0); 
            }                   // see GNU docs, "system" also works                
            else {  printf("from parent: mpg123 is pid %d\nENTER to quit\n", x);
                    sprintf(kil,"%s%d",kil,x);
                    getchar();  // wait for user input
                    system(kil);
                    printf("All ");
            }       /* witness that the "else if" and "else" blocks are both executed here in parallel. The "else" 
       (parent) block is continuous with the rest of the program (since the PARENT PROCESS is actually
       the program itself) so... */
            printf("done.\n");
            exit(0);
    }
    Get it? Anyway, that might be all you need.
    hi
    i tried this long back.
    but i am unable to play the mp3 and all
    i donno what the wrong with me.
    while executing the exe i got some prints in the terminal
    from parent: mpg123 is pid 3163
    ENTER to quit
    and i did not find the mpg123 in my machine (FEDORA 9).
    (i this is the problem).

    will u please make me correct.

  13. #13
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    You need to install the mpg123-*.rpm package(s). [Only the binaries are necessary. If there isn't one in your current distribution, you can probably find one on the web, for example here: http://rpmfind.net/linux/rpm2html/se...p?query=mpg123

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  14. #14
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    For simple playback of sounds, if you're developing for KDE4, you can use Phonon, which I've heard is pretty nice to work with.

    Other than that, there's a multitude of sound libraries, like SDL's sound parts, OpenAL, etc. These are low-level; for high-level playback, there's e.g. Xinelib or gstreamer.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. How to play a sound
    By asofaihp in forum C++ Programming
    Replies: 16
    Last Post: 09-02-2009, 09:37 PM
  2. Simple Blackjack Program
    By saber1357 in forum C Programming
    Replies: 1
    Last Post: 03-28-2009, 03:19 PM
  3. Sound in a c program
    By c u r != me in forum C Programming
    Replies: 0
    Last Post: 03-22-2009, 04:07 PM
  4. 'C' windows sound program...
    By Klint in forum Windows Programming
    Replies: 2
    Last Post: 06-02-2005, 01:50 AM
  5. this is how you can play wavs/mp3s in a C++ program
    By Shadow12345 in forum C++ Programming
    Replies: 2
    Last Post: 12-06-2002, 05:35 PM