mad_fixed_t random_value(void) { mad_fixed_t result; float tmp = (rand()/(RAND_MAX+1.0))-0.5; result = mad_f_tofixed(tmp); return result; }
int main(int argc, char* argv[]) { FILE *fp1; FILE *fp2; FILE *fp3; mad_fixed_t X[num_inp], T[num_out], H[num_hid], Y[num_out]; mad_fixed_t W_xh[num_inp][num_hid], W_hy[num_hid][num_out]; mad_fixed_t dW_xh[num_inp][num_hid], dW_hy[num_hid][num_out]; mad_fixed_t Q_h[num_hid], Q_y[num_out]; mad_fixed_t dQ_h[num_hid], dQ_y[num_out]; mad_fixed_t delta_h[num_hid], delta_y[num_out]; mad_fixed_t sum, mse; int Icycle, Itrain; int i, j, h; fp1 = fopen(train_file, "r"); fp2 = fopen(weight_file, "w"); fp3 = fopen(mse_file, "w"); if (fp1 == NULL) { puts("File not exist !!"); getchar(); exit(1); } srand((int)time(0)); for (h = 0; h < num_hid; h++) { for (i = 0; i < num_inp; i++) { W_xh[i][h] = random_value(); dW_xh[i][h] = F_ZERO; } } for (j = 0; j <= num_out; j++) { for (h = 0; h < num_hid; h++) { W_hy[h][j] = random_value(); dW_hy[h][j] = F_ZERO; } } for (h = 0; h < num_hid; h++) { Q_h[h] = F_ZERO; dQ_h[h] = F_ZERO; delta_h[h] = F_ZERO; } for (j = 0; j < num_out; j++) { Q_y[j] = random_value(); dQ_y[j] = F_ZERO; delta_y[j] = F_ZERO; } /*start learning */ float tmp; for (Icycle = 0; Icycle < num_cycle; Icycle++) { mse = F_ZERO; fseek(fp1, 0, 0); for (Itrain = 0; Itrain < num_train; Itrain++) { for (i = 0; i < num_inp; i++) { tmp = parser(fp1); X[i] = mad_f_tofixed(tmp); } for (j = 0; j < num_out; j++) { tmp = parser(fp1); T[j]= mad_f_tofixed(tmp); } for (h = 0; h < num_hid; h++) { sum = F_ZERO; for (i = 0; i < num_inp; i++) { sum = mad_f_add(sum, mad_f_mul(X[i], W_xh[i][h])); } /* H[h] = (float)1.0 / (1.0 + exp(-(sum - Q_h[h]))); */ tmp = exp(-1.0 * mad_f_todouble(mad_f_sub(sum, Q_h[h]))); mad_fixed_t exp_result = mad_f_tofixed(tmp); H[h] = mad_f_div(F_POS_ONE, mad_f_add(F_POS_ONE, exp_result)); } for (j = 0; j < num_out; j++) { sum = F_ZERO; for (h = 0; h < num_hid; h++) { sum = mad_f_add(sum, mad_f_mul(H[h], W_hy[h][j])); } /* Y[j] = (float)1.0 / (1.0 + exp(-(sum - Q_y[j]))); */ tmp = exp(-1.0 * mad_f_todouble(mad_f_sub(sum, Q_y[j]))); mad_fixed_t exp_result = mad_f_tofixed(tmp); Y[j] = mad_f_div(F_POS_ONE, mad_f_add(F_POS_ONE, exp_result)); } for (j = 0; j < num_out; j++) { /* delta_y[j] = Y[j] * (1.0 - Y[j]) * (T[j] - Y[j]); */ mad_fixed_t first, second, third; first = Y[j]; second = mad_f_sub(F_POS_ONE, Y[j]); third = mad_f_sub(T[j], Y[j]); delta_y[j] = mad_f_mul(mad_f_mul(first, second), third); } for (h = 0; h < num_hid; h++) { sum = F_ZERO; for (j = 0; j < num_out; j++) { /* sum = sum + W_hy[h][j] * delta_y[j]; */ sum = mad_f_add(sum, mad_f_mul(W_hy[h][j], delta_y[j])); } /* delta_h[h] = H[h] * (1.0 - H[h]) * sum; */ mad_fixed_t first, second, third; first = H[h]; second = mad_f_sub(F_POS_ONE, H[h]); third = sum; delta_h[h] = mad_f_mul(mad_f_mul(first, second), sum); } for (j = 0; j < num_out; j++) { for (h = 0; h < num_hid; h++) { /* dW_hy[h][j] = eta * delta_y[j] * H[h] + alpha * dW_hy[h][j]; */ mad_fixed_t first, second; first = mad_f_mul(mad_f_mul(F_ETA, delta_y[j]), H[h]); second = mad_f_mul(F_ALPHA, dW_hy[h][j]); dW_hy[h][j] = mad_f_add(first, second); } } for (j = 0; j < num_out; j++) { /* dQ_y[j] = -eta * delta_y[j] + alpha * dQ_y[j]; */ mad_fixed_t first, second; first = mad_f_mul(F_NEG_ETA, delta_y[j]); second = mad_f_mul(F_ALPHA, dQ_y[j]); dQ_y[j] = mad_f_add(first, second); } for (h = 0; h < num_hid; h++) { for (i = 0; i < num_inp; i++) { /* dW_xh[i][h] = eta * delta_h[h] * X[i] + alpha * dW_xh[i][h]; */ mad_fixed_t first, second; first = mad_f_mul(X[i], mad_f_mul(F_ETA, delta_h[h])); second = mad_f_mul(F_ALPHA, dW_xh[i][h]); dW_xh[i][h] = mad_f_add(first, second); } } for (h = 0; h < num_hid; h++) { /* dQ_h[h] = -eta * delta_h[h] + alpha * dQ_h[h]; */ mad_fixed_t first, second; first = mad_f_mul(F_NEG_ETA, delta_h[h]); second = mad_f_mul(F_ALPHA, dQ_h[h]); dQ_h[h] = mad_f_add(first, second); } for (j = 0; j < num_out; j++) { for (h = 0; h < num_hid; h++) { /* W_hy[h][j] = W_hy[h][j] + dW_hy[h][j]; */ tmp = mad_f_todouble(W_hy[h][j]); W_hy[h][j] = mad_f_add(W_hy[h][j], dW_hy[h][j]); } } for (j = 0; j < num_out; j++) { /* Q_y[j] = Q_y[j] + dQ_y[j]; */ Q_y[j] = mad_f_add(Q_y[j], dQ_y[j]); } for (h = 0; h < num_hid; h++) { for (i = 0; i < num_inp; i++) { /* W_xh[i][h] = W_xh[i][h] + dW_xh[i][h]; */ W_xh[i][h] = mad_f_add(W_xh[i][h], dW_xh[i][h]); } } for (h = 0; h < num_hid; h++) { /* Q_h[h] = Q_h[h] + dQ_h[h]; */ Q_h[h] = mad_f_add(Q_h[h], dQ_h[h]); } for (j = 0; j < num_out; j++) { /* mse += (T[j] - Y[j]) * (T[j] - Y[j]); */ mad_fixed_t first, second; first = mad_f_sub(T[j], Y[j]); second = mad_f_sub(T[j], Y[j]); mse = mad_f_add(mse, mad_f_mul(first, second)); } } /* mse = mse / num_train; */ mse = mad_f_div(mse, mad_f_tofixed(num_train)); if ((Icycle % 10) == 9) { printf("\nIcycle=%3d \nmse=%-8.6f\n", Icycle, mad_f_todouble(mse)); fprintf(fp3,"%3d \n%-8.6f\n", Icycle, mad_f_todouble(mse)); } } printf("\n"); for (h = 0; h < num_hid; h++) { for (i = 0; i < num_inp; i++) { printf("W_xh[%2d][%2d]=%-8.4f\t", i, h, mad_f_todouble(W_xh[i][h])); fprintf(fp2,"%-8.4f\t", mad_f_todouble(W_xh[i][h])); } printf("\n"); fprintf(fp2,"\n"); } printf("\n"); fprintf(fp2,"\n"); for (j = 0; j < num_out; j++) { for (h = 0; h < num_hid; h++) { printf("W_hy[%2d][%2d]=%-8.4f\t", h, j, mad_f_todouble(W_hy[h][j])); fprintf(fp2,"%-8.4f\t", mad_f_todouble(W_hy[h][j])); } printf("\n"); fprintf(fp2,"\n"); } printf("\n"); fprintf(fp2,"\n"); for (h = 0; h < num_hid; h++) { printf("Q_h[%2d]=%-8.4f\t", h, mad_f_todouble(Q_h[h])); fprintf(fp2,"%-8.4f\t", mad_f_todouble(Q_h[h])); } printf("\n\n"); fprintf(fp2,"\n\n"); for (j = 0; j < num_out; j++) { printf("Q_y[%2d]=%-8.4f\t", j, mad_f_todouble(Q_y[j])); fprintf(fp2,"%-8.4f\t", mad_f_todouble(Q_y[j])); } printf("\n\n"); fprintf(fp2,"\n\n"); fclose(fp1); fclose(fp2); fclose(fp3); return 0; }
#include <math.h> #include <time.h> #include <mad.h> #define num_cycle 3000 #define num_train 1500 #define num_inp 2 #define num_hid 4 #define num_out 1 #define eta 0.5 #define alpha 0.2 #define train_file "test.txt" #define weight_file "pwm.wei" #define mse_file "pwm.mes" const mad_fixed_t F_POS_ONE = mad_f_tofixed((float)1.0); const mad_fixed_t F_POS_TWO = mad_f_tofixed((float)2.0); const mad_fixed_t F_NEG_ONE = mad_f_tofixed((float)-1.0); const mad_fixed_t F_ZERO = mad_f_tofixed((float)0.0); const mad_fixed_t F_POS_RDDO = mad_f_tofixed((float)0.5); const mad_fixed_t F_NEG_RDDO = mad_f_tofixed((float)-0.5); const mad_fixed_t F_ALPHA = mad_f_tofixed((float)alpha); const mad_fixed_t F_ETA = mad_f_tofixed((float)eta); const mad_fixed_t F_NEG_ETA = mad_f_tofixed((float)-eta); float parser(FILE *fp) { char c; char str[50], *p; float res;
int main(int argc, char *argv[]) { int fd = 0; char *currentfile, old_dir[PATH_MAX]; playlist *pl = NULL; struct id3_file *id3struct = NULL; struct id3_tag *id3tag = NULL; int retval; buffer playbuf; struct mad_decoder decoder; pthread_t keyb_thread; key_t sem_key; key_t mem_key; key_t frames_key; union semun sem_ops; int shm_id; int frames_id; mad_decoder_position = 0; output_buffer_position = 0; old_dir[0] = '\0'; playbuf.pl = pl = new_playlist(); if (!pl) { fprintf(stderr, "malloc failed at startup!\n"); exit(1); } loop_remaining = 1; options.volume = MAD_F_ONE; status = MPG321_PLAYING; /* Get the command line options */ parse_options(argc, argv, pl); if(options.opt & MPG321_PRINT_FFT) if(!(options.opt & MPG321_REMOTE_PLAY)) { /* printf("FFT analysis can only be used in Remote mode play.\n\n"); */ usage(argv[0]); exit(0); } /* If there were no files and no playlist specified just print the usage */ if (!playlist_file && optind == argc) { usage(argv[0]); exit(0); } if (playlist_file) load_playlist(pl, playlist_file); if(options.opt & MPG321_RECURSIVE_DIR) add_cmdline_files_recursive_dir(pl, argv); else add_cmdline_files(pl, argv); if (shuffle_play) shuffle_files(pl); if(options.opt & MPG321_ENABLE_BUFFER) { /* Initialize semaphore and shared memeory */ if(access(argv[0],X_OK) == 0) sem_key = ftok(argv[0],0); else sem_key = ftok(MPG321_PATH,0); if(sem_key == -1) { perror("Cannot obtain resources for semaphores"); exit(EXIT_FAILURE); } semarray = semget(sem_key,3,IPC_CREAT | IPC_EXCL | S_IRWXU); if(semarray == -1) { perror("Cannot initialize semaphores"); exit(EXIT_FAILURE); } sem_ops.val = buffer_size-1; if(semctl(semarray,0,SETVAL,sem_ops) == -1) { perror("Error while initializing mad_decoder semaphore"); if(semctl(semarray,0,IPC_RMID) == -1) perror("Error while destroying semaphores"); goto out; //exit(EXIT_FAILURE); } sem_ops.val = 0; if(semctl(semarray,1,SETVAL,sem_ops) == -1) { perror("Error while initializing mad_decoder semaphore"); if(semctl(semarray,0,IPC_RMID) == -1) perror("Error while destroying semaphores"); goto out; //exit(EXIT_FAILURE); } sem_ops.val = 0; if(semctl(semarray,2,SETVAL,sem_ops) == -1) { perror("Error while initializing mad_decoder semaphore"); if(semctl(semarray,0,IPC_RMID) == -1) perror("Error while destroying semaphores"); goto out; //exit(EXIT_FAILURE); } /* Shared Memory */ mem_key = ftok(argv[0],1); shm_id = shmget(mem_key,buffer_size * sizeof(output_frame), IPC_CREAT | S_IREAD | S_IWRITE); if(shm_id == -1) { perror("Cannot initialize shared buffer"); goto out; //exit(EXIT_FAILURE); } Output_Queue = shmat(shm_id,NULL,0); if(*(int *)Output_Queue == -1) { perror("Error while attaching shared buffer to mad_decoder"); if(shmctl(shm_id,IPC_RMID,NULL)) perror("Cannot destroy shared buffer"); goto out; //exit(EXIT_FAILURE); } static int n; for(n=0;n<buffer_size;n++) { memset((Output_Queue+n)->data,'\0',4608); memset((Output_Queue+n)->time,'\0',80); (Output_Queue+n)->length = 0; (Output_Queue+n)->seconds = 0; (Output_Queue+n)->num_frames = 0; } frames_key = ftok(argv[0],2); frames_id = shmget(frames_key,buffer_size * sizeof(decoded_frames), IPC_CREAT | S_IREAD | S_IWRITE); if(frames_id == -1) { perror("Cannot initialize shared frames counter"); goto out; //exit(EXIT_FAILURE); } Decoded_Frames = shmat(frames_id,NULL,0); if(*(int *)Decoded_Frames == -1) { perror("Error while attaching shared frames counter to mad_decoder"); if(shmctl(frames_id,IPC_RMID,NULL)) perror("Cannot destroy shared frames counter"); goto out; //exit(EXIT_FAILURE); } Decoded_Frames->is_http = 0; Decoded_Frames->is_file = 0; } else { ao_initialize(); check_default_play_device(); } if (!(options.opt & MPG321_REMOTE_PLAY)) { handle_signals(-1); /* initialize signal handler */ remote_input_buf[0] = '\0'; } if (!(options.opt & MPG321_QUIET_PLAY)) mpg123_boilerplate(); if (options.opt & MPG321_REMOTE_PLAY) { printf ("@R MPG123\n"); if(options.opt & MPG321_ENABLE_BUFFER) { #ifdef HAVE_ALSA init_alsa_volume_control("default"); /* For the moment use "default", it works on most of the systems. Tested in Debian,Fedora,Ubuntu,RedHat,CentOS,Gentoo */ if(options.volume != MAD_F_ONE) mpg321_alsa_set_volume((long)options.volume*volume_max/100); #endif } } /* Fork here. */ if(options.opt & MPG321_ENABLE_BUFFER) { output_pid = fork(); if(output_pid == -1) { perror("Error while forking output process"); goto out; /* Release shared memeory and semaphores */ // exit(EXIT_FAILURE); } if(output_pid == 0) { frame_buffer_p(); exit(EXIT_SUCCESS); } signal(SIGUSR1,handle_signals); if(!(options.opt & MPG321_REMOTE_PLAY)) { #ifdef HAVE_ALSA init_alsa_volume_control("default"); if(options.volume != MAD_F_ONE) mpg321_alsa_set_volume((long)options.volume*volume_max/100); #endif } } if( (options.volume != MAD_F_ONE) && !(options.opt & MPG321_ENABLE_BUFFER)) { options.volume = mad_f_tofixed((long)options.volume/100.0); } else{ options.volume = MAD_F_ONE; /* When using the buffer options.volume when decoding each frame should be equal to MAD_F_ONE */ // options.volume = mad_f_tofixed((long)100.0/100.0); } if (!(options.opt & MPG321_REMOTE_PLAY)) { if(options.opt & MPG321_ENABLE_BASIC) { /* Now create and detach the basic controls thread */ sem_init(&main_lock,0,0); pthread_create(&keyb_thread,NULL,read_keyb,NULL); pthread_detach(keyb_thread); } } if(set_xterm) { tty_control(); get_term_title(title); }else { if (!(options.opt & MPG321_REMOTE_PLAY)) { if (tcgetattr(0, &terminal_settings) < 0) perror("tcgetattr()"); memcpy(&old_terminal_settings, &terminal_settings, sizeof(struct termios)); /* Early thread start */ sem_post(&main_lock); } } /* Play the mpeg files or zip it! */ while((currentfile = get_next_file(pl, &playbuf))) { //printf("Current File: %s\n",currentfile); if (quit_now) break; signal(SIGINT, SIG_DFL); playbuf.buf = NULL; playbuf.fd = -1; playbuf.length = 0; playbuf.done = 0; playbuf.num_frames = 0; current_frame = 0; playbuf.max_frames = -1; strncpy(playbuf.filename,currentfile, PATH_MAX); playbuf.filename[PATH_MAX-1] = '\0'; if (status == MPG321_PLAYING || status == MPG321_STOPPED) file_change = 1; mad_timer_reset(&playbuf.duration); mad_timer_reset(¤t_time); id3struct = NULL; if (!(options.opt & MPG321_QUIET_PLAY) && file_change) { /* id3struct = id3_file_open (currentfile, ID3_FILE_MODE_READONLY);*/ if (id3struct == NULL) get_id3_info(currentfile, &id3struct, &id3tag); if(id3tag) show_id3(id3tag); } scrobbler_time = -1; if(options.opt & MPG321_USE_SCROBBLER) { if(id3struct == NULL) get_id3_info(currentfile,&id3struct,&id3tag); if (id3tag) { char emptystring[31], emptyyear[5] = " "; int i; if(parse_id3(scrobbler_args, id3tag)) { memset(emptystring, ' ', 30); emptystring[30] = '\0'; if((options.opt & MPG321_VERBOSE_PLAY) && (options.opt & MPG321_USE_SCROBBLER)) { fprintf(stderr, "\nPreparing for the AudioScrobbler:\n"); for(i = 0; i < 6; i++) { if(scrobbler_args[i] == NULL) scrobbler_args[i] = ( i == 3 ? emptyyear: emptystring); fprintf(stderr, "- %s\n", scrobbler_args[i]); } } } } } if (options.opt & MPG321_REMOTE_PLAY && file_change) { if(id3struct == NULL) get_id3_info(currentfile, &id3struct, &id3tag); if(id3tag) { if (!show_id3(id3tag)) { /* This shouldn't be necessary, but it appears that libid3tag doesn't necessarily know if there are no id3 tags on a given mp3 */ char * basec = strdup(currentfile); char * basen = basename(basec); char * dot = strrchr(basen, '.'); if (dot) *dot = '\0'; printf("@I %s\n", basen); free(basec); } } else { char * basec = strdup(currentfile); char * basen = basename(basec); char * dot = strrchr(basen, '.'); if (dot) *dot = '\0'; printf("@I %s\n", basen); free(basec); } } if(id3struct != NULL) id3_file_close(id3struct); /* Create the MPEG stream */ /* Check if source is on the network */ if((fd = raw_open(currentfile)) != 0 || (fd = http_open(currentfile)) != 0 || (fd = ftp_open(currentfile)) != 0) { playbuf.fd = fd; playbuf.buf = malloc(BUF_SIZE); playbuf.length = BUF_SIZE; if(options.opt & MPG321_ENABLE_BUFFER) { Decoded_Frames->is_http = 1; Decoded_Frames->is_file = 0; } calc_http_length(&playbuf); mad_decoder_init(&decoder, &playbuf, read_from_fd, read_header, /*filter*/0, output, handle_error, /* message */ 0); } /* Check if we are to use stdin for input */ else if(strcmp(currentfile, "-") == 0) { playbuf.fd = fileno(stdin); playbuf.buf = malloc(BUF_SIZE); playbuf.length = BUF_SIZE; mad_decoder_init(&decoder, &playbuf, read_from_fd, read_header, /*filter*/0, output, handle_error, /* message */ 0); } /* currentfile is a local file (presumably.) mmap() it */ else { struct stat stat; if((fd = open(currentfile, O_RDONLY)) == -1) { mpg321_error(currentfile); /* Restore TTY from keyboard reader thread */ if(options.opt & MPG321_ENABLE_BASIC) if (tcsetattr(0, TCSANOW, &old_terminal_settings) < 0) perror("tcsetattr ICANON"); if(set_xterm) { set_tty_restore(); osc_print(0,0,title); if (ctty) fclose(ctty); } if( options.opt & MPG321_REMOTE_PLAY) if(remote_restart) { clear_remote_file(pl); /* If restart is enabled, restart remote shell when file doesn't exist*/ continue; } if(options.opt & MPG321_ENABLE_BUFFER) goto out; else exit(1); /* mpg123 stops immediately if it can't open a file */ /* If sth goes wrong break!!!*/ break; } if(options.opt & MPG321_ENABLE_BUFFER) { Decoded_Frames->is_http = 0; Decoded_Frames->is_file = 1; } if(fstat(fd, &stat) == -1) { mpg321_error(currentfile); close(fd); continue; } if (!S_ISREG(stat.st_mode)) { if(S_ISFIFO(stat.st_mode)) { fallback = 1; goto fall_back_to_read_from_fd; } close(fd); continue; } retval = calc_length(currentfile, &playbuf); //FIXME Check also if it is an mp3 file. If not break and go to the next file possible if(retval < 0) { if(options.opt & MPG321_REMOTE_PLAY) { fprintf(stderr,"@E Corrupted file: %s\n",currentfile); close(fd); if(remote_restart) { clear_remote_file(pl); /* If restart is enabled, restart remote shell when file is corrupted */ continue; } break; } mpg321_error(currentfile); close(fd); // break; //FIXME Break and stop OR continue the playlist ???? continue; } if((options.opt & MPG321_VERBOSE_PLAY) && (options.opt & MPG321_USE_SCROBBLER)) fprintf(stderr, "Track duration: %ld seconds\n",playbuf.duration.seconds); if(options.opt & MPG321_USE_SCROBBLER) scrobbler_set_time(playbuf.duration.seconds); if ((options.maxframes != -1) && (options.maxframes <= playbuf.num_frames)) { playbuf.max_frames = options.maxframes; } playbuf.frames = malloc((playbuf.num_frames + 1) * sizeof(void*)); playbuf.times = malloc((playbuf.num_frames + 1) * sizeof(mad_timer_t)); #ifdef __uClinux__ if((playbuf.buf = mmap(0, playbuf.length, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED) #else if((playbuf.buf = mmap(0, playbuf.length, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) #endif { mpg321_error(currentfile); continue; } playbuf.frames[0] = playbuf.buf; mad_decoder_init(&decoder, &playbuf, read_from_mmap, read_header, /*filter*/0, output, handle_error, /* message */ 0); fall_back_to_read_from_fd: //FIXME. Reported that on some embedded systems with low memory, less than 16MB doesn't work properly. if(fallback) { playbuf.fd = fd; playbuf.buf = malloc(BUF_SIZE); playbuf.length = BUF_SIZE; mad_decoder_init(&decoder, &playbuf, read_from_fd, read_header, /*filter*/0, output, handle_error, /* message */ 0); fallback = 1; } } if(!(options.opt & MPG321_QUIET_PLAY))/*zip it!!!*/ { /* Because dirname might modify the argument */ char * dirc = strdup(currentfile); char * basec = strdup(currentfile); char * basen = basename(basec); char * dirn = dirname(dirc); /* make sure that the file has a pathname; otherwise don't print out a Directory: listing */ if(strchr(currentfile, '/') && strncmp(old_dir, dirn, PATH_MAX) != 0) { /* Print information about the file */ fprintf(stderr, "\n"); fprintf(stderr,"Directory: %s\n", dirn); strncpy(old_dir, dirn, PATH_MAX); old_dir[PATH_MAX-1] = '\0'; } /* print a newline between different songs only, not after Directory: listing */ else { fprintf(stderr, "\n"); } fprintf(stderr,"Playing MPEG stream from %s ...\n", basen); /* Printing xterm title */ if(set_xterm) { osc_print(0,0,basen); } free(dirc); free(basec); } signal(SIGINT, handle_signals); signal(SIGCHLD, handle_sigchld); /*Give control back so that we can implement SIG's*/ if(set_xterm) { set_tty_restore(); if (tcgetattr(0, &terminal_settings) < 0) perror("tcgetattr()"); memcpy(&old_terminal_settings, &terminal_settings, sizeof(struct termios)); /* disable canonical mode processing in the line discipline driver */ terminal_settings.c_lflag &= ~(ICANON | ECHO); /* apply our new settings */ if (tcsetattr(0, TCSANOW, &terminal_settings) < 0) perror("tcsetattr ICANON"); if(options.opt & MPG321_ENABLE_BASIC) { /* Late thread start */ sem_post(&main_lock); } } /* Every time the user gets us to rewind, we exit decoding, reinitialize it, and re-start it */ if(options.opt & MPG321_ENABLE_BUFFER) { Decoded_Frames->total_decoded_frames = 0; Decoded_Frames->done = 0; } while (1) { decoder.options |= MAD_OPTION_IGNORECRC; mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC); if(options.opt & MPG321_ENABLE_BUFFER) { static struct sembuf start_sops = {2,-1,0}; semop(semarray,&start_sops,1); mad_decoder_position = 0; output_buffer_position = 0; union semun sem_ops; sem_ops.val = 0; semctl(semarray,2,SETVAL,sem_ops); Decoded_Frames->total_decoded_frames = 0; Decoded_Frames->done = 0; Decoded_Frames->is_http = 0; Decoded_Frames->is_file = 0; } /* if we're rewinding on an mmap()ed stream */ if(status == MPG321_REWINDING && playbuf.fd == -1) { mad_decoder_init(&decoder, &playbuf, read_from_mmap, read_header, /*filter*/0, output, /*error*/0, /* message */ 0); } else break; } if (!(options.opt & MPG321_QUIET_PLAY)) { char time_formatted[11]; mad_timer_string(current_time, time_formatted, "%.1u:%.2u", MAD_UNITS_MINUTES, MAD_UNITS_SECONDS, 0); fprintf(stderr," \r"); fprintf(stderr, "\n[%s] Decoding of %s finished.\n",time_formatted, basename(currentfile)); /* Report total decoded seconds. Maybe for the frame buffer report only total played time?? */ } if (options.opt & MPG321_REMOTE_PLAY && status == MPG321_STOPPED) { clear_remote_file(pl); } mad_decoder_finish(&decoder); if (playbuf.frames) free(playbuf.frames); if (playbuf.times) free(playbuf.times); if (playbuf.fd == -1) { munmap(playbuf.buf, playbuf.length); close(fd); } else { free(playbuf.buf); if (playbuf.fd != fileno(stdin)) close(playbuf.fd); } } if(!(options.opt & MPG321_ENABLE_BUFFER)) { if(playdevice) ao_close(playdevice); ao_shutdown(); } if (!(options.opt & MPG321_REMOTE_PLAY)) { if(options.opt & MPG321_ENABLE_BASIC) { pflag = 1; /* Restore TTY from keyboard reader thread */ if (tcsetattr(0, TCSANOW, &old_terminal_settings) < 0) perror("tcsetattr ICANON"); } } /*Restoring TTY*/ if(set_xterm) { set_tty_restore(); osc_print(0,0,title); if (ctty) fclose(ctty); } out: if(options.opt & MPG321_ENABLE_BUFFER) { if(kill(output_pid,SIGUSR1) == -1) perror("Error while stopping output process"); static int wstatus; wait(&wstatus); if(wstatus == -1) perror("Error while waiting for output process to exit"); if(semctl(semarray,0,IPC_RMID) == -1) perror("Error while destroying semaphores"); if(shmdt(Output_Queue) == -1) perror("Error while detaching shared buffer"); if(shmctl(shm_id,IPC_RMID,NULL)) perror("Cannot destroy shared buffer"); if(shmctl(frames_id,IPC_RMID,NULL)) perror("Cannot destroy shared buffer"); } return(0); }
/* Basic control keys thread */ void *read_keyb(void *ptr) { int ch; long bvolume = 0; sem_wait(&main_lock); /* Get the current terminal settings for the first time*/ if (tcgetattr(0, &terminal_settings) < 0) perror("tcgetattr()"); memcpy(&old_terminal_settings, &terminal_settings, sizeof(struct termios)); terminal_settings.c_lflag &= ~(ICANON | ECHO); if (tcsetattr(0, TCSANOW, &terminal_settings) < 0) perror("tcsetattr ICANON"); if(options.opt & MPG321_ENABLE_BUFFER) { // init_alsa_volume_control("default"); #ifdef HAVE_ALSA bvolume = mpg321_alsa_get_volume(); #endif Decoded_Frames->timer = -1; } else volume = (int)((double)options.volume / (1 << MAD_F_FRACBITS) * 100.0); while(!pflag) { ch = getchar(); if(ch == KEY_CTRL_VOLUME_DOWN) { if(options.opt & MPG321_ENABLE_BUFFER) { #ifdef HAVE_ALSA bvolume = mpg321_alsa_get_volume(); bvolume = bvolume - round(0.02*volume_max); /* 1dB decrement ? */ #endif Decoded_Frames->timer = 1; } else { count = 1; volume -= 3; } if(options.opt & MPG321_ENABLE_BUFFER) { #ifdef HAVE_ALSA if(bvolume < volume_min) bvolume = volume_min; Decoded_Frames->bvolume = 100*bvolume/volume_max; #endif } else { if(volume < 0) volume = 0; } if(options.opt & MPG321_ENABLE_BUFFER) { #ifdef HAVE_ALSA mpg321_alsa_set_volume(bvolume); #endif } else options.volume = mad_f_tofixed(volume / 100.0); if(!(options.opt & MPG321_VERBOSE_PLAY)) { #ifdef HAVE_ALSA if(options.opt & MPG321_ENABLE_BUFFER) fprintf(stderr,"Volume: %lu%% \r",100*bvolume/volume_max); else{ #endif if(!(options.opt & MPG321_ENABLE_BUFFER)) fprintf(stderr,"Volume: %ld%% \r",volume); #ifdef HAVE_ALSA } #endif } } if(ch == KEY_CTRL_VOLUME_UP) { if(options.opt & MPG321_ENABLE_BUFFER) { #ifdef HAVE_ALSA bvolume = mpg321_alsa_get_volume(); bvolume = bvolume + round(0.02*volume_max); /* 1dB increment? */ #endif Decoded_Frames->timer = 1; } else { count = 1; volume += 3; } if(options.opt & MPG321_ENABLE_BUFFER) { #ifdef HAVE_ALSA if(bvolume > volume_max) bvolume = volume_max; Decoded_Frames->bvolume = 100*bvolume/volume_max; #endif } else { if(volume > 100) volume = 100; } if(options.opt & MPG321_ENABLE_BUFFER) { #ifdef HAVE_ALSA mpg321_alsa_set_volume(bvolume); #endif } else options.volume = mad_f_tofixed(volume / 100.0); if(!(options.opt & MPG321_VERBOSE_PLAY)) { #ifdef HAVE_ALSA if(options.opt & MPG321_ENABLE_BUFFER) fprintf(stderr,"Volume: %lu%% \r",100*bvolume/volume_max); else{ #endif if(!(options.opt & MPG321_ENABLE_BUFFER)) fprintf(stderr,"Volume: %ld%% \r",volume); #ifdef HAVE_ALSA } #endif } } if(ch == KEY_CTRL_NEXT_SONG) { kill(getpid(),SIGINT); } if(ch == KEY_CTRL_MUTE) { if(!muted) { muted = 1; #ifdef HAVE_ALSA if(options.opt & MPG321_ENABLE_BUFFER) mpg321_alsa_set_volume((long)0.0); else #endif options.volume = mad_f_tofixed(0.0); } else { muted = 0; #ifdef HAVE_ALSA if(options.opt & MPG321_ENABLE_BUFFER) mpg321_alsa_set_volume(bvolume); else #endif options.volume = mad_f_tofixed(volume / 100.0); } } } if (tcsetattr(0, TCSANOW, &old_terminal_settings) < 0) perror("tcsetattr ICANON"); return (void *)0; }
/**************************************************************************** * Command-line arguments parsing. We use two methods and two command-line * * formats depending on the system type. On unix system we apply the good * * old getopt() method, other system are offered a really primitive options * * interface. * ****************************************************************************/ static int ParseArgs(int argc, char * const argv[]) { int DoPhoneFilter=0, i; double AmpFactor; mad_fixed_t Amp=MAD_F_ONE; #ifdef HAVE_GETOPT /* This version is for Unix systems. */ int Option; /* Parse the command line. */ while((Option=getopt(argc,argv,"a:p"))!=-1) switch(Option) { /* {5} Set the amplification/attenuation factor, expressed * in dB. */ case 'a': /* If the current linear amplification factor is not * one (MAD_F_ONE) then is was already set. Setting it * again is not permitted. */ if(Amp!=MAD_F_ONE) { fprintf(stderr,"%s: the amplification/attenuation factor " "was set several times.\n",ProgName); return(1); } /* The decibel value is converted to a linear factor. * That factor is checked against the maximum value * that can be stored in a mad_fixed_t. The upper * bound is MAD_F_MAX, it is converted to a double * value with mad_f_todouble() for comparison. */ AmpFactor=pow(10.,atof(optarg)/20); if(AmpFactor>mad_f_todouble(MAD_F_MAX)) { fprintf(stderr,"%s: amplification out of range.\n", ProgName); return(1); } /* Eventually the amplification factor is converted * from double to fixed point with mad_f_tofixed(). */ Amp=mad_f_tofixed(AmpFactor); break; /* {6} The output is filtered through a telephone wire. */ case 'p': /* Only one occurrence of the option is permitted. */ if(DoPhoneFilter) { fprintf(stderr,"%s: the phone-line simulation option " "was already set.\n",ProgName); return(1); } /* The output will be filtered through a band-pass * filter simulating a phone line transmission. */ DoPhoneFilter=1; break; /* Print usage guide for invalid options. */ case '?': default: PrintUsage(); return(1); } #else /* HAVE_GETOPT */ /* This other version is for non-Unix systems. */ /* Scan all command-line arguments. */ for(i=1;i<argc;i++) { /* Set the amplification factor if the current argument looks * like a number. Look at the comment of the case marked {5} * in the Unix section for details. */ if(*argv[i]=='+' || *argv[i]=='-' || isdigit(*argv[i])) { if(Amp!=MAD_F_ONE) { fprintf(stderr,"%s: the amplification/attenuation factor " "was set several times.\n",ProgName); return(1); } AmpFactor=pow(10.,atof(argv[i])/20); if(AmpFactor>mad_f_todouble(MAD_F_MAX)) { fprintf(stderr,"%s: amplification out of range.\n", ProgName); return(1); } Amp=mad_f_tofixed(AmpFactor); } else /* Use the phone-like filter if the argument is the * * 'phone' string. Look at the comment of the case marked * {6} in the Unix section for details. */ if(strcmp(argv[i],"phone")==0) { if(DoPhoneFilter) { fprintf(stderr,"%s: the phone-line simulation option " "was already set.\n",ProgName); return(1); } DoPhoneFilter=1; } else { /* The argument is not a recognized one. Print the * usage guidelines and stop there. */ PrintUsage(); return(1); } } #endif /* HAVE_GETOPT */ /* Initialize the subband-domain filter coefficients to one if * filtering is requested. */ if(Amp!=MAD_F_ONE || DoPhoneFilter) for(i=0;i<32;i++) Filter[i]=MAD_F_ONE; /* The amplification/attenuation is applied to the subband-domain * filter definition. */ if(Amp!=MAD_F_ONE) { DoFilter=1; for(i=0;i<32;i++) Filter[i]=Amp; } /* The telephone-like filter is applied to the subband-domain * filter definition. All subbands are set to zero except bands 2 * to 6. This programs author has no access to the MPEG audio * specification, he does not know the frequencies bands covered * by the MPEG subbands. */ if(DoPhoneFilter) { DoFilter=1; Filter[0]=MAD_F(0); for(i=5;i<32;i++) Filter[i]=MAD_F(0); } /* Command-line arguments are okay. */ return(0); }