0

我对 Android 中的 UI 线程有疑问:

我的活动扩展了 AsyncTask 以对波形文件进行一些计算。如果我运行一次应用程序,大约需要 15 分钟才能完成。这对我来说不是问题。我想多次启动该过程(例如4次,因为我有4个波形文件)所以我希望时间为1小时(15分钟* 4 = 1小时),但事实并非如此,它持续大约3小时 !

为了多次启动进程,我创建了一个调用“new ProcessTask().execute();”的函数 4次,我在“onPostExecute”中调用了这个函数

你知道为什么我多次运行它需要更多时间吗?

在此先感谢您的帮助

public  void processingRespiratoryFiles() {

        if(p<=MainActivity.count)
        {
        filePath = Environment.getExternalStorageDirectory() + "/external_sd/AudioRecorder/audio"+p+".wav";

        File filein = new File(filePath);
        if (filein.exists()) 
            new ProcessTask().execute();


        }
        else
        {
        RespiratoryHandling(ODI_Sum,0);
        Index.setText(Double.toString(ODI_Sum));
        message2=ODI_Sum;
        }


    }





private class ProcessTask extends AsyncTask<Void, Void, Integer> {

        ProgressDialog dialog;

        @Override
        protected Integer doInBackground(Void... params) {
            return process(filePath);
        }

        @Override
        protected void onPostExecute(Integer result) {////////////////////////////////////////////////////////
            dialog.dismiss();
            if (result > -1)
            {
                p++;
                ODI=(double)result/NumberOfHours;
                ODI_Sum+=ODI;
                processingRespiratoryFiles();


            }
        }

        @Override
        protected void onPreExecute() {
            dialog = ProgressDialog.show(
                    Diagnose.this, "Diagnosing, please wait",
                    "Processing...");
        }
    }


    /**
     * Reset ring buffer for filter process before filtering signal
     * @param alength number of a coefficients
     * @param blength number of a coefficients
     */
    public void resetRingBuffer(int alength, int blength) {
        xv = new double[blength + 1];
        yv = new double[alength + 1];

        px = 0;
        py = 0;
    }

    /**
     * Filter each second of signal and then compute the energy of output
     * @param din input stream of audio file
     * @param length number of read samples
     * @param numChannels number of channels of signal
     * @return energy value of 1 second filtered signal 
     */
    public double readEnergyFiltered(DataInputStream din, int length,
            int numChannels) {
        double energy = 0.0;

        try {
            byte[] byteBuffer = new byte[length * 2 * numChannels]; // 16 bit

            // read length samples from file's stream
            int r = din.read(byteBuffer); // bytes read
            // if reach to end of file
            if (r == -1)
                return -1.0;
            r = r / (2 * numChannels); // samples read

            // apply the filter
            for (int i = 0; i < r; ++i) {
                // get the new sample
                short sample = (short) ((byteBuffer[2 * numChannels * i] & 0xff) | (byteBuffer[2
                        * numChannels * i + 1] & 0xff) << 8);
                xv[px] = (double) sample / 32768.0;

                // compute the output
                double y = bcoef[0] * xv[px];
                for (int j = 1; j < bcoef.length; ++j)
                    y += bcoef[j] * xv[(px - j + xv.length) % xv.length];
                for (int j = 1; j < acoef.length; ++j)
                    y -= acoef[j] * yv[(py - j + yv.length) % yv.length];

                // save the result
                yv[py] = y;

                // update energy
                energy += y * y;

                // increment the index of the ring buffer
                px = (px + 1) % xv.length;
                py = (py + 1) % yv.length;
            }

            return energy;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return -1.0;
    }

    /**
     * Process the filtering, computing energy and estimating number of events 
     * @param filePath path to audio file on sd card
     * @return number of events
     */
    private int process(String filePath) {
        try {
            int event = 0;
            double sum =0.0;

            byte[] header = new byte[44];

            File filein = new File(filePath);
            FileInputStream fin = new FileInputStream(filein);
            BufferedInputStream bin = new BufferedInputStream(fin);
            DataInputStream din = new DataInputStream(bin);

            din.read(header);

            // Sample Rate
            int fs = (header[24] & 0xff) | (header[25] & 0xff) << 8
                    | (header[26] & 0xff) << 16 | (header[27] & 0xff) << 24;
            double Ts = 1.0 / fs;
            Log.v("PERM", "Sample Rate: " + String.valueOf(fs));

            // Num Channels
            int numChannels = (header[22] & 0xff) | (header[23] & 0xff) << 8;
            Log.v("PERM", "Num Channel: " + String.valueOf(numChannels));

            // Bits Per Sample
            int bitsPerSample = (header[34] & 0xff) | (header[35] & 0xff) << 8;
            Log.v("PERM", "Bits per sample: " + String.valueOf(bitsPerSample));

            // Sample Rate
            int numBytes = (header[40] & 0xff) | (header[41] & 0xff) << 8
                    | (header[42] & 0xff) << 16 | (header[43] & 0xff) << 24;
            int N = numBytes / numChannels / (bitsPerSample / 8);
            Log.v("PERM", "Data Length: " + String.valueOf(N));

            // Calibration phase
            // Find average energy for the first 180 seconds
            double energy = 0.0;
            resetRingBuffer(acoef.length, bcoef.length);
            for (int i = 0; i < 30; i++) {
                sum = readEnergyFiltered(din, fs, numChannels);
                energy += sum * Ts;
            }
            if(MainActivity.count==1)
            {
             mean_energy = energy / 30.0;
             ThresholdR = 0.8 * mean_energy;
            }

            Log.v("PERM", "Threshold: " + String.valueOf(ThresholdR));

            // process hold file
            resetRingBuffer(acoef.length, bcoef.length);
            din.close();
            bin.close();
            fin.close();

            fin = new FileInputStream(filein);
            bin = new BufferedInputStream(fin);
            din = new DataInputStream(bin);
            din.read(header);

            N = N / fs;
            int j = 1;
            while (j <= N) {
                int counter = 0;
                //int trigger = 0;
                energy = readEnergyFiltered(din, fs, numChannels) * Ts;
                if (energy >= 0.) {

                    Log.v("PERM", "Energy " + String.valueOf(energy));
//while ((energy <= Threshold) || (trigger < 4))
                    while ((energy < ThresholdR)) {
                        counter++;
                        energy = readEnergyFiltered(din, fs, numChannels) * Ts;
                        Log.v("PERM", "Inner Energy " + String.valueOf(energy));
                        if (energy < 0)
                            break;
                        //trigger++;
                    }
                }

                if (counter > 10)
                    event++;

                if (counter > 0)
                    j += counter;
                else
                    j++;
            }

            Log.v("PERM", "Event: " + String.valueOf(event));

            din.close();
            bin.close();
            fin.close();

            return event;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return -1;
    }
4

1 回答 1

3

确实需要在 IntentService 中完成。如果您使用 AsyncTask 并意外翻转设备,您的 Activity 将重新启动并且 AsyncTask 将消失。IntentService 将允许您“移动”远离当前活动。

虽然,我不得不说,如果你愿意等待 15 分钟让 AsyncTask 完成,那么你的应用程序是不寻常的。

于 2013-03-15T23:15:18.097 回答