Skip to content

Commit

Permalink
Added mpg123 error handling, updated README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
arkrow committed Jan 12, 2023
1 parent bc95f5a commit a7c2966
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 21 deletions.
20 changes: 14 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ The following software must be installed for `pymusiclooper` to function correct

- [Python](https://www.python.org/downloads/) >= 3.6
- [ffmpeg](https://ffmpeg.org/download.html) (adds support for MP3 and other audio formats)
- [mpg123](https://www.mpg123.de/download.shtml) to play/preview music loops through the terminal
- [mpg123](https://www.mpg123.de/download.shtml) to play/preview music loops through the terminal (Note: pymusiclooper will still work without mpg123, however terminal playback will not be available, disabling the following functionalities: the default --play option, and the loop preview function in interactive mode)

### Installing using pip

Expand Down Expand Up @@ -60,6 +60,8 @@ Export:
-t, --txt export the loop points of a track in samples and append to a loop.txt
file (compatible with LoopingAudioConverter).
--stdout print the loop points of a track in samples to stdout (Standard Output)
Batch Options:
-r, --recursive process directories and their contents recursively (has an effect only if
the given path is a directory).
-f, --flatten flatten the output directory structure instead of preserving it when
Expand All @@ -82,7 +84,7 @@ PyMusicLooper will find the best loop point it can detect, and will then, depend

(b) export intro/loop/outro sections of the song (currently outputs as WAV-only; however you may convert them with [ffmpeg](https://ffmpeg.org/) or [Audacity](https://www.audacityteam.org/));

(c) export the loop points (in samples) to a text file compatible with [LoopingAudioConverter](https://github.com/libertyernie/LoopingAudioConverter/), which you can use for audio loops in custom theme creation, game engine audio loops, etc.
(c) export the loop points (in samples) directly or to a text file compatible with [LoopingAudioConverter](https://github.com/libertyernie/LoopingAudioConverter/), which you can use for audio loops in custom theme creation, game engine audio loops, etc.

**Note**: using the interactive `-i` option is highly recommended, since the algorithmically chosen "best" loop point may not be perceptually good, mainly due to some chosen loop points causing 'sound popping' when played.

Expand All @@ -106,12 +108,18 @@ Export the song into intro, loop and outro files.
pymusiclooper -e "TRACK_NAME.ogg"
```

Export the loop points of all the songs in a particular directory to a single loop.txt file (compatible with [LoopingAudioConverter](https://github.com/libertyernie/LoopingAudioConverter/)).
Export the loop points (in samples) of all the songs in a particular directory to a single loop.txt file (compatible with [LoopingAudioConverter](https://github.com/libertyernie/LoopingAudioConverter/)).

```sh
pymusiclooper -t "/path/to/dir/"
```

Instead of exporting the file into loop segments, the discovered loop points can be output directly to the CLI as sample points

```sh
pymusiclooper "/path/to/track.mp3" --stdout
```

Note: each line in loop.txt follows the following format: `{loop-start} {loop-end} {filename}`

### Miscellaneous
Expand All @@ -132,10 +140,10 @@ pymusiclooper "TRACK_NAME.wav" -e -i

### Example of multiple functionalities in action

Export intro/loop/outro sections and loop points of all the songs in the current directory and its subdirectories, to a folder called "Music Loops", processing 4 tracks concurrently, preserving the original tags.
Export intro/loop/outro sections and loop points of all the songs in the current directory and its subdirectories, to a folder called "Music Loops", processing 4 tracks concurrently.

```sh
pymusiclooper -ret . -o "Music Loops" -n 4 --preserve-tags
pymusiclooper -ret . -o "Music Loops" -n 4
```

## Building from source
Expand All @@ -162,7 +170,7 @@ This project started out as a fork of [Nolan Nicholson](https://github.com/Nolan

## Version History

- v2.5.1 Added workaround for libsndfile mp3 loading issue; fixed error handling when no loop points were found or when audio has not been loaded.
- v2.5.1 Added workaround for libsndfile mp3 loading issue; fixed error handling when no loop points were found, when audio has not been loaded or when mpg123 is unavailable.
- v2.5.0 Added option to print loop points to terminal STDOUT (contributed by Coolsonickirby). Project relicensed to MIT license as of v2.5+.
- v2.4.0 Temporarily disabled preserve_tags features to resolve dependency installation issues; pending re-implementation.
- v2.3.0 Partial code re-organization and improvement; better exception handling
Expand Down
19 changes: 7 additions & 12 deletions pymusiclooper/argparser.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from argparse import ArgumentParser
from argparse import ArgumentParser, ArgumentTypeError


class ArgParser(ArgumentParser):
Expand All @@ -8,6 +8,7 @@ def __init__(self, *args, **kwargs):

play_options = self.add_argument_group("Play")
export_options = self.add_argument_group("Export")
batch_options = self.add_argument_group("Batch Options")
general_options = self.add_argument_group("General Options")

self.add_argument(
Expand Down Expand Up @@ -39,12 +40,6 @@ def __init__(self, *args, **kwargs):
default=False,
help="export the song into intro, loop and outro files (WAV format).",
)
export_options.add_argument(
"--preserve-tags",
action="store_true",
default=False,
help="export with the track's original tags. [currently disabled]",
)
export_options.add_argument(
"-t",
"--txt",
Expand All @@ -58,21 +53,21 @@ def __init__(self, *args, **kwargs):
default=False,
help="print the loop points of a track in samples to stdout (Standard Output)",
)
export_options.add_argument(
batch_options.add_argument(
"-r",
"--recursive",
action="store_true",
default=False,
help="process directories and their contents recursively (has an effect only if the given path is a directory).",
)
export_options.add_argument(
batch_options.add_argument(
"-f",
"--flatten",
action="store_true",
default=False,
help="flatten the output directory structure instead of preserving it when using the --recursive flag.",
)
export_options.add_argument(
batch_options.add_argument(
"-n",
"--n-jobs",
type=int,
Expand All @@ -91,12 +86,12 @@ def bounded_float(x):
try:
x = float(x)
except ValueError:
raise argparse.ArgumentTypeError(
raise ArgumentTypeError(
"%r not a floating-point literal" % (x,)
)

if x <= 0.0 or x >= 1.0:
raise argparse.ArgumentTypeError(
raise ArgumentTypeError(
"%r is not between 0.0 and 1.0" % (x,)
)
return x
Expand Down
11 changes: 8 additions & 3 deletions pymusiclooper/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,11 +278,16 @@ def frames_to_ftime(self, frame):
return "{:02.0f}:{:06.3f}".format(time_sec // 60, time_sec % 60)

def play_looping(self, loop_start, loop_end, start_from=0):
from mpg123 import ENC_FLOAT_32, Out123
try:
from mpg123 import ENC_FLOAT_32, Out123

out = Out123()
out = Out123()

out.start(self.rate, self.channels, ENC_FLOAT_32)
out.start(self.rate, self.channels, ENC_FLOAT_32)
except Exception as e:
logging.error('An issue related to the mpg123 library for playback has occured. If it is not installed/functional, alternatively use the export fucntionalities such as --export . See ` pymusiclooper --help ` for a full list of options.')
logging.error(e)
return

playback_frames = librosa.util.frame(self.playback_audio.flatten(order="F"), frame_length=2048, hop_length=512)
loop_start = loop_start * self.channels
Expand Down

0 comments on commit a7c2966

Please sign in to comment.