Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Forum Updated on Feb 6th

    Unable to call .first of array[SOLVED]

    Tools
    1
    3
    1094
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • O
      ogopa last edited by

      Hi guys,
      I have two problems:
      Problem number 1: I am using pcm.c to build a gui to generate sine waves using user input. I have integrated the code into Qt Creator and I compiled and ran the code with no errors.
      However, every time I click the pushButton (which is supposed to output the sine wave), my program terminates. I have tracked the problem code. In my pushButton function, I have called a function called write_loop which calls generate_sine(). This is causing the problem. I have debugged the code in generate_sine() and I found out that the line which causes it to terminate is this one:
      @if ((areas[chn].first % 8) != 0) {
      printf("areas[%i].first == %i, aborting...", chn , areas[chn].first);
      exit(EXIT_FAILURE);
      }@
      I found out that the problem is that it is refusing to use this specific code: @areas[chn].first@. Also, I did a check to see areas[chn].first is divisible by 8 and it is for all the values of chn. THis program seems only to have the problem of calling areas[chn].first. I have found the problem, but now I don't know how to fix it. Any help would be greatly appreciated.

      The code I have under my pushButton function(on_pushButton_clicked) and generate_sine.cpp is shown below.

      generate_sine.cpp:
      @void generate_sine(snd_pcm_channel_area_t *areas,
      snd_pcm_uframes_t offset,
      int count, double *_phase)
      {
      static double max_phase = 2. * M_PI;
      double phase = _phase;
      double step = max_phase
      freq/(double)rate;
      unsigned char samples[channels];
      int steps[channels];
      unsigned int chn;
      int format_bits = snd_pcm_format_width(format);
      unsigned int maxval = (1 << (format_bits - 1)) - 1;
      int bps = format_bits / 8; /
      bytes per sample */
      int phys_bps = snd_pcm_format_physical_width(format) / 8;
      int big_endian = snd_pcm_format_big_endian(format) == 1;
      int to_unsigned = snd_pcm_format_unsigned(format) == 1;
      int is_float = (format == SND_PCM_FORMAT_FLOAT_LE ||
      format == SND_PCM_FORMAT_FLOAT_BE);
      float amplitude_scale = amplitude/8.56;

         //  verify and prepare the contents of areas
           for (chn = 0; chn < channels; chn++) {
                   if (areas[chn].first!=0) {
                           printf("areas[%i].first == %i, aborting...", chn , areas[chn].first);
                           exit(EXIT_FAILURE);
                   }
                   samples[chn] = (((unsigned char *)areas[chn].addr) + (areas[chn].first / 8));
                   if (areas[chn].step !=0) {
                           printf("areas[%i].step == %i, aborting...  ", chn, areas[chn].step);
                           exit(EXIT_FAILURE);
                   }
                   steps[chn] = areas[chn].step / 8;
                   samples[chn] += offset * steps[chn];
           }
         //fill the channel areas
           while (count-- > 0) {
                   union {
                           float f;
                           int i;
                   } fval;
                   int res, i;
                   if (is_float) {
                           fval.f = amplitude_scale * sin(phase) * maxval;
                           res = fval.i;
                   } else
                           res = amplitude_scale * sin(phase) * maxval;
                   if (to_unsigned)
                           res ^= 1U << (format_bits - 1);
                   for (chn = 0; chn < channels; chn++) {
                           /* Generate data in native endian format */
                           if (big_endian) {
                                   for (i = 0; i < bps; i++)
                                           *(samples[chn] + phys_bps - 1 - i) = (res >> i * 8) & 0xff;
                           } else {
                                   for (i = 0; i < bps; i++)
                                           *(samples[chn] + i) = (res >>  i * 8) & 0xff;
                           }
                           samples[chn] += steps[chn];
                   }
                   phase += step;
                   if (phase >= max_phase)
                           phase -= max_phase;
           }
           *_phase = phase;
      

      }@
      more code posted below because of word limit

      1 Reply Last reply Reply Quote 0
      • O
        ogopa last edited by

        on_pushButton_clicked():
        @void wave::on_pushButton_clicked()
        {

        struct transfer_method {
                 const char *name;
                 snd_pcm_access_t access;
                 int (*transfer_loop)(snd_pcm_t *handle,
                                      signed short *samples,
                                      snd_pcm_channel_area_t *areas);
         };
        
         static struct transfer_method transfer_methods[] = {
        
        
                   { "write", SND_PCM_ACCESS_RW_INTERLEAVED, write_loop },
                   { NULL, SND_PCM_ACCESS_RW_INTERLEAVED, NULL }
         };
        
                snd_pcm_t *handle;
                int err;
                snd_pcm_hw_params_t *hwparams;
                snd_pcm_sw_params_t *swparams;
                int method = 0;
                signed short *samples;
                unsigned int chn;
                snd_pcm_channel_area_t *areas;
        
                snd_pcm_hw_params_alloca(&hwparams);
                snd_pcm_sw_params_alloca(&swparams);
        
                  err = snd_output_stdio_attach(&output, stdout, 0);
                if (err < 0) {
                        printf("Output failed: %s" , snd_strerror(err));
        
                }
        
        
                if ((err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
                        printf("Playback open error: %s", snd_strerror(err));
        
                }
        
                if ((err = set_hwparams(handle, hwparams, transfer_methods[method].access)) < 0) {
                        printf("Setting of hwparams failed: %s", snd_strerror(err));
                        exit(EXIT_FAILURE);
                }
                if ((err = set_swparams(handle, swparams)) < 0) {
                        printf("Setting of swparams failed: %s", snd_strerror(err));
                        exit(EXIT_FAILURE);
                }
        
                if (verbose > 0)
                        snd_pcm_dump(handle, output);
        
                samples = new signed short [period_size * channels * snd_pcm_format_physical_width(format)];
                if (samples == NULL) {
                        printf("Not enough memory");
                        exit(EXIT_FAILURE);
                }
        
                areas = new snd_pcm_channel_area_t [channels];
                if (areas == NULL) {
                        printf("Not enough memory");
                        exit(EXIT_FAILURE);
                }
                for (chn = 0; chn < channels; chn++) {
                        areas[chn].addr = samples;
                        areas[chn].first = chn * snd_pcm_format_physical_width(format);
                        areas[chn].step = channels * snd_pcm_format_physical_width(format);
                }
        
               err = transfer_methods[method].transfer_loop(handle, samples, areas);
        
                delete [] areas;
                delete []samples;
                snd_pcm_close(handle);
        

        }@

        Problem number 2:
        When I set my while loop in the write_loop function to 'true', i.e while(isTrue), (when bool isTrue = true; is defined at the top), my program immediately terminates. And to make sure that it isn't the generate_sine() function that isn't doing it(as described above, I commented the generate_sine() function out, and it still just terminates. However, If I don't set any value for bool isTrue (i.e. just define bool isTrue; at the top, the program doesn't terminate.
        Here is my write_loop function:
        @int write_loop(snd_pcm_t *device_handle,
        signed short *samples,
        snd_pcm_channel_area_t *areas)
        {
        double phase = 0;
        signed short *ptr;
        int err, cptr;

                     generate_sine(areas, 0, period_size, &phase);
             while (isTrue) {
        
        
        
                     ptr = samples;
                     cptr = period_size;
                     while (cptr > 0) {
                             err = snd_pcm_writei(device_handle, ptr, cptr);
        
                             if (err == -EAGAIN)
                                     continue;
                             if (err < 0) {
                                     if (xrun_recovery(device_handle, err) < 0) {
                                             printf("Write error: %s  ", snd_strerror(err));
                                             exit(EXIT_FAILURE);
                                     }
                                     break;  // skip one period
                             }
                             ptr += err * channels;
                             cptr -= err;
                     }
             }
        

        }
        @

        1 Reply Last reply Reply Quote 0
        • O
          ogopa last edited by

          solved. areas had different values as it was declared again.

          1 Reply Last reply Reply Quote 0
          • First post
            Last post