stunes.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <unistd.h>
  4. #include "math.h"
  5. #include "./st.h"
  6. #include "./config.h"
  7. /* lots o ambition to develop this project, for example, one could make use of pthread to generate a thread for each of the instruments,
  8. the args could represent filenames to files consisting of rhythms as well as the frequency and/or type of wave
  9. rhythms would be defined as 10001000 for example, where 0 translates to skip an iteration
  10. each of the threads would be generating output to be | into aplay, to generate music
  11. surely it works!
  12. if threading doesnt work out, work out how to add mutliple frequencies together? */
  13. void die() {
  14. printf("\
  15. usage: stunes <file> [<file> ...]\n\
  16. - up to 8 files can be specified\n");
  17. exit(1);
  18. }
  19. /* enums */
  20. /* data types */
  21. typedef struct {
  22. char type;
  23. char* load;
  24. } line;
  25. /* function declarations */
  26. int read_rhythm(FILE*, int);
  27. line parse_line(FILE*);
  28. /* variables */
  29. /* collection of error messages */
  30. static char* errmesgs[2] = {
  31. "all ok",
  32. "invalid syntax (check config.h for available symbols)",
  33. };
  34. /* function implementations */
  35. /* reads a line into a string, if the line is structured validly */
  36. /* skips the first character and all whitespaces up to the actual payload */
  37. /* before \n */
  38. /* returns a line struct with the probed character signifying the type of */
  39. /* line, as well as the additional contents of the line */
  40. /* returns -1 as the line type if the line type was not recognized */
  41. line parse_line(FILE* in)
  42. {
  43. char c;
  44. char ret = -1;
  45. long read;
  46. // TODO: fix parsing bug when comment immediately follows empty line
  47. c = probe_line(in, symbols, &read);
  48. if (c == -1) {
  49. line l1 = { -1, "" };
  50. return l1;
  51. }
  52. /* set recognized line type */
  53. if (in_array(symbols, c)) ret = c;
  54. /* skip whitespaces and comments */
  55. if (ret == '\n' || ret == '#') {
  56. /* set pointer in file to correct pos */
  57. skip(in, '\n');
  58. /* return 'ignore' line type */
  59. line l2 = { '-', "" };
  60. return l2;
  61. }
  62. /* line type was recognized, now scan for size of the line load */
  63. /* this doesn't check for whitespaces (which are later ignored), so the */
  64. /* char buffer will usually be a little bigger in size than the actual load */
  65. int chars = seek_char(in, '\n');
  66. char load[chars];
  67. char* loadp = load;
  68. if (ret != -1) {
  69. /* consume type character, since we already knwo the type */
  70. c = getc(in);
  71. while (!feof(in) && c != '\n') {
  72. c = getc(in);
  73. if (c == ' ') continue;
  74. *loadp = c;
  75. loadp++;
  76. }
  77. *loadp = '\0';
  78. }
  79. /* actual data */
  80. line l3 = { ret, load };
  81. return l3;
  82. }
  83. /* parses the rhythm of a rhythm file */
  84. /* on failure returns the error code that references an 'errmesgs' error, */
  85. /* otherwise 0 */
  86. int read_rhythm(FILE* in, int channel)
  87. {
  88. char* seq;
  89. char* t;
  90. int freq;
  91. // TODO: actually use the data and save structs
  92. line l;
  93. for (int i = 0; i < 5; i++) {
  94. l = parse_line(in);
  95. if (l.type == -1) return 1;
  96. if (l.type == '-') continue;
  97. printf("LOAD %s FIN\n", l.load);
  98. printf("TYPE %c FIN\n", l.type);
  99. printf("i %i\n", i);
  100. }
  101. return 0;
  102. /* old, replaced by function pointers soon */
  103. enum wav type;
  104. if (strcmp(t, "wcon") == 0) {
  105. type = wcon;
  106. } else if (strcmp(t, "wsin") == 0) {
  107. type = wsin;
  108. } else if (strcmp(t, "wcos") == 0) {
  109. type = wcos;
  110. } else if (strcmp(t, "wtan") == 0) {
  111. type = wtan;
  112. } else {
  113. type = wcon;
  114. }
  115. rhythm ch = { seq, type, freq };
  116. channels[channel] = ch;
  117. printf("parsed channel %i\n", channel);
  118. return 0;
  119. }
  120. int main(int argc, char **argv) {
  121. /* ensure user is not retarded */
  122. if (argc < 2 || argc > 9)
  123. die();
  124. int ret;
  125. /* loop argument files */
  126. for (int ch = 0; ch < argc-1; ch++) {
  127. int arg = ch + 1;
  128. FILE* f = fopen(argv[arg], "r");
  129. /* fopen returned NULL */
  130. if (f == NULL) {
  131. fprintf(stderr, "error while opening file %s for reading, ignoring...\n", argv[arg]);
  132. continue;
  133. }
  134. /* read rhythm of file */
  135. if ((ret = read_rhythm(f, ch))) {
  136. /* in case of error, print 'errmesgs' element specified by ret */
  137. fprintf(stderr, "error while reading file %s: %s\nignoring file %s...\n", argv[arg], errmesgs[ret], argv[arg]);
  138. continue;
  139. }
  140. }
  141. return 0;
  142. }