Hosting [Status: fully functional, likely to switch to another host soon]
The app code is hosted by Google Sites (as this allows for a quick template approach and works well) as an embedded block.
Audio track and document storage, and access: all playable tracks are hosted on Dropbox (one of the few that allows track streaming in their free account). The app accesses these on demand as a media stream from dropbox, hence the device does need internet access for this process. Sheet music is simply held on a Google Drive and shared with the app (Google Drive as I have plenty of space on my account!)
Given that the code is embedded in Google Sites, we only need to share a link to the Google Sites site for full access.
Functionality (currently in use)
Each Voice Page has a full set of playable audio controls linked to an individual practice track for that piece and voice.
Tapping the play button will play that track as a stream from Dropbox (see above) and so internet access is needed.
In this version there is no extra protection against internet drops, so if the internet is lost the track will complete via the buffered data (if enough time into the track for a fully buffer to be downloaded to the app). If the buffer is not complete, then it will play through the data that is in the buffer and then stop. If the internet is restored before the buffer runs out, then there will be no gap in play, or if at the end of the track, the next track will start. In this version, if the internet is not reinstated before the end of track, and a playlist is playing, then the system will try to pull in the next track and fail, causing the audio control to fail and the page will need to be refreshed. This will be addressed in the next version.
The audio control has a slider/progress bar. As a track plays the slider indicates progress (alongside a numerical time indicator). Sliding the bar can be used to move around in the playing track. There is also a mute toggle button on the control.
Each track has a 3-dot menu. This has 2 extra options, allowing the user to download the track to their device, and also to alter the playback speed. Unfortunately, downloading the track does not then provide the function of playing the track in the app without an internet link, but it can be played by the device's music player app.
Associate with each track audio control is a 'Repeat Counter' box (similar to [x1]). Tapping this opens a flyout that allows the number to be changed. At the moment this only affects the playlist, not manual play with the control's play button. When playing through a playlist, each track will play through the number of times indicated in this box. For example, if the box shows [x2] then the track will play through twice before moving on to the next track. NB this does not currently change live whilst playing. If the track is playing and the number is increased, it will only play the number of times that was indicated by the box at the start of play. This is addressed in the next version (see below).
Below the playable audio controls is a playlist section. This is accessed by tapping the expandable 'Playlist Controls' button. Doing so will reveal playlist control buttons and a loop option setting. Below this is a track list that matches the tracks in the audio controls above.
The control buttons are mostly clear in their labelling.
Play All: select each track to activate for playing and then start the first track playing. Subsequently, each track will play in turn. As above, if the 'Repeat Box' is set to more than 1 then the track will play through the number of times indicate before moving on.
Play Selected: this is the same as Play All, but does not select tracks to play. The user should select the tracks that they want to play before tapping 'Play Selected'. All playback rules apply.
Stop: as expected this stops the playlist playing. It does not act as a pause button (the Pause Button is in the next version) so hitting play again after Stop, will start back at the beginning.
Previous and Next: these stop playing the current track and jump to and start playing the next or previous tracks.
Clear: this deselects all tracks.
Loop [checkbox]: If selected then, after the last track in the playlist is played, the system will continue with the first track again.
Below the playlist buttons there is a full track-list, with 3 purposes:
Each track has a tickbox [checkbox] to allow tracks to be selected and de-selected. If 'Play Selected' is used, then only selected tracks will be played.
To the right there is an indication re the number of repeats for this track (see 1.4 above). There is no function associated with this feature, it is for information only.
When tracks are playing, the track is highlighted in the list.
Known Issues With this Version:
No Internet drop-out protection. The tracks buffer when starting to play and will fully buffer for that track in a short time. If the internet drops while buffering, and remains down, the track will play to the end of the buffer which will be before the end of the track. If fully buffered that track will complete. The issue here is that, when the buffer is used up, the system tries to access more of that track, or if completed, the next track. This will fail and the track will lock (it becomes greyed out). The only solution for that track is then to refresh the whole page which will cancel any playback setup. These issues are rare, but do happen. Protection (but not guarantee) is provided in the next version.
No track reorder available. This is present in the next version.
Scrolling issues:
Some have reported that the scrolling does not work cleanly. Some have not been able to scroll at all, others only a small amount. Advice was given that, if the scroll was applied over the page banner then after that the page scrolls normally. It is not clear whether this happens in the next version. An acceptable workaround, but not ideal.
No facility to skip sections of a track that aren't sung, so long delays for the singer. It would also be useful to be able to skip back to repeat a section of difficult practice. Plans not in place for this in the next version as, without clever protocols or AI, the skip points would all need to be setup manually.
Version 2 is in alpha-testing. Notes on features, development and plans:
The app code is now hosted on Cloudflare. The active link from Cloudflare is embed as code on pages setup on Google Sites (as this allows for a quick template approach and works well).
The code had to be moved to Cloudflare (originally it was all on Google Sites) as some of the code needed to 'store locally', but this is blocked by Google Sites. This was to allow for persistence, e.g. reordering the tracks and then coming back later and having them still in the order that was set.
Functioning Features in V2:
As above, persistence is now fully functioning allowing user to make changes once for all following sessions.
Track reordering functioning but buttons very difficult to use. Solution: place buttons side-by-side and a little larger
Track spacing is very narrow: Solution separate the tracks more.
Internet dropout is still a thing. Solution: see below.
Sheet music icon looks more like a music icon. Solution: Change the icon.
The repeat bubble has the flyout too far over to the right, meaning that we can't increase the count. Solution: move the flyout to align to the right side of the bubble extending further over to the left (not right). Temporary workaround: open the repeat flyout in portrait, then rotate the screen and the flyout becomes visible.
The track list and its buttons are not aesthetically pleasing: Solution: get AI to suggest something better. If that doesn't work, look at popular playlist apps for ideas!
Issues to resolve / features to add to V2:
Though there is some evidence that internet dropout protection is working, it is not 100%. Various car journeys have shown this, but there is evidence of an improvement.
Solutions:
Caching of all tracks fully when the internet is live, each time the app is started. This would only be for the chosen voice.
A one-off download of all tracks, either by file transfer, or start caching and continue until all local and permanently stored. Playback is then via local file. This can be just for the selected voice, or all voices. If just the selected voice then there will be a one-off download each time a voice is opened for the first time.
A mix of solutions may be that we cache the next 2 songs at the same time. This gives more time for the return of the internet but does not take up large amounts of local storage. We also need to know what the next 2 songs will be, but if we are in 'Shuffle' mode we would have to know what's coming next (possible but more awkward).
More robust internet dropout protection.
Discussion:
The most robust, guaranteed solution is Option 2, as, once all tracks are stored, we are simply carrying out local playback. However, this will involve quite a lot of storage on phones that are used for other things. We also have to think about the future, where more events will be added. If we wish to keep each event then the storage quota will increase. It also means that if a choir member uses the app on a different device, all tracks need to be stored locally again, not major but not ideal.
Option 1 is an extension of what is being done now, but it means that everytime the app is run or refreshed all tracks will be downloaded. This could be a big hit on the data budget of an avid practice enthusiast.
Option 3 would reduce breakup further but has issues and may require recoding for shuffle mode
Option 4, for a very solid internet link, is the ideal. However, no-one likes breaks in transmission. Even we can guarantee that there will be 100% protection against audio control lockup due to lost internet, we will still have occasional breaks in playback
A lot comes down to how patchy mobile internet is for different people. A strong internet with little travel to unkown areas may just be best with some increased dropout protection. However, patchy internet would be better served by the full download and play locally method. On the other hand, if it's rare and people are willing to put up with it then maybe we go with option 4 anyway.